节点上线和下线的逻辑--
节点下线分为两种--心跳失败主动或被动和主节点断开连接,但是节点本身没有发生重启;第二种就是节点宕机重启--其实这两中情况下处理逻辑都是一样的,只是节点本身如果还能消费到kafka的时候可以继续执行任务但是不能从kafka中拉取新的消息,因为此时自己无法获取消息的投票信息,在执行的过程中可以提交;执行完之后还没有重新加入集群则应该断开和kafka的链接---
可以不和kafka断开连接的原因是此时自己和kafka的消息不回被其他节点消费,所以执行队列中的任务可以正常执行并提交;但是存疑队列中无法举证所以只能等待----具体看是否要等待执行完;--主要综合考虑存疑队列;
消息消费模型--
如何保证一个消息只会被执行一次---从几个方面保证--一个消息最多可能存在于两个节点中(除非多个节点都在执行消息的时候失败,这种概率是很小的),消息出现在其他节点中的情况--partition重分配,则该节点执行队列中的消息可能被其他节点消费,但是只会进入到其他节点的存疑队列中,而不是直接被执行,存疑队列通过举证和执行检查策略保证该消息没有即将被执行或者正在被执行或者最终被执行完成;才可以重新执行;---有一种情况,该节点开始执行任务了,但是此时断开和主节点的链接,而恰好其他节点对该任务举证,这会导致该任务有可能被其他节点执行---这里需要在每个任务执行前向主节点汇报;
几个确定性机制可以保证消息不会被重复执行--
- 投票进入执行队列中的任务肯定可以被执行---在和主节点正常连接的情况下;
- 和主节点断开连接的节点不能继续执行任务,可能错过举证,需要清空执行队列;
- 任务执行前需要向主节点汇报--保证该任务在执行过程中和主节点断开连接不会让该任务被其他执行;---断开连接就清空执行队列保证未执行的任务在断开连接之后可以被其他节点执行,但是自己不会再重复执行;
- 存异队列中的任务必须通过举证--通过举证则证明主节点运行正常;
- 举证通过保证没有节点即将执行该任务或者正在执行该任务;--对于即将执行的任务可以采取重新分配的策略;或者使用监听策略;正在执行的任务使用超时+检查来确定该任务的最终执行情况;
- 一种情况---节点A准备执行任务a,向主节点发送了a的prepare信息,开始执行,但是在执行过程中主节点失败,重新选举,导致a的prepare信息丢失,同时节点A没有加入到新集群中--没有和新的主节点建立连接,此时节点B对任务a发起举证,会导致a举证通过,(举证完成之后运行检查策略节点A没有执行完,此时节点B运行检查策略也会通过)节点B准备执行a,这种情况下会导致任务a同时被AB两个节点执行----这种情况无法避免,通过时差来保证,或者全节点同步prepare信息来保证,但是会影响性能,可以想办法降低概率来保证---目前只有这种情况会导致同一个任务被多个节点执行;
- 未开始执行的任务不会导致这种情况发生--因为节点和主节点断开连接之后不会执行新的任务,而是要重新举证才可以执行;而通过举证的消息