任务调度中执行不一致

时间:2019-02-13 07:39:27

标签: redis locking distributed-system taskscheduler

我正在编写一个任务计划组件,以便仅应执行计时器任务 一次在重复的调度程序(即应用服务器)集群中,并且 当前使用分布式锁来提高可靠性。

分布式锁由Redis记录实现。当任务提交给调度程序A时, 调度程序B将使用SETNX(原子)并在Redis服务器中写入任务记录。 如果另一个调度程序正在提交完全相同的任务(例如,向用户发送电子邮件), SETNX将失败,然后在调度程序B中取消调度。

我的问题发生在一种特殊情况下,描述如下:

   scheduler A              Redis         scheduler B        scheduler C
             |      lock      |               |                   
             |--------------->|      lock     |                   
             |     success    |<--------------|                   
             |<---------------|      fail     |                   
task alpha   o                |-------------->|                   
  submit     |                |               x schedule          
 success     |                |                 canceled          0 a new scheduler
             |                |                                   | is scaled in cluster
             |                |         fetch existing tasks      |
             |                |<----------------------------------|
             |                |        report submitted tasks     |
             |                |---------------------------------->| now scheduler C
             |                |                                   | knows task alpha.
             |                |                                   |
task alpha   o      lock      |                lock               o task alpha
  starts     |--------------->|<----------------------------------|   starts
 execute     |      fail      |              success              |  execute
             |<---------------|---------------------------------->| 
 schedule    x                |                                   | keep executing
 canceled                     |                                   |
                              |                                   |
                              |                                   |
                              x Redis fail                        |
                                                                  |
                                              unlock              v execution success
                               <----------------------------------| delete task record
                                                                  |
                        Redis 0                                   |
                    recovered |                                   |
                              |              0 scheduler B
                   the record |     fetch    | recovered
                of task alpha |<-------------|
                 still exists |    report    |
                              |------------->| task alpha needs
                              |     lock     o execution because
                              |<-------------| time has arrived!
                              |    success   |
                              |------------->|
                              |              |
                              |    unlock    v execution success (inconsistent execution)
                              |<-------------|
                                             |
                                             |

在此图中,task alpha由调度程序C执行。但是,由于解锁失败, 任务记录未从Redis删除。之后,当调度程序B恢复时, 该任务将再次执行,从而导致不一致

通常,不假定基本服务Redis发生故障,这会导致此问题 是一个罕见的问题。始终可以将Redis视为同步记录的重复集群 彼此之间,Redis的失败意味着所有重复的Redis节点均已死亡。

详细描述,但简短的问题:

  • 如何解决不一致问题?
  • 上述方案是否还有其他更好的调度程序设计?

0 个答案:

没有答案