一:使用的kafka中可能碰到的一致性问题
1.Producer的一致性
如前篇所讲,假如对 登录系统,主流程是:用户请求-->验证账户密码-->返回成功;一些其他流程包括:积分、提醒、荣誉系统等;这里有个问题是:如果这两者有一个失败了怎么办?
2.Brokers的一致性(不是重点,这个是由kafka自己保证的)
由于Message由Producer发送到Topic的Master Partition的时候,为了保证可靠性,会等待In-Sync的Replicas都同步完成之后才会返回成功;这里同样有个问题:如果返回超时怎么办?
3.Consumer的一致性
在Consumer的客户端,为了提高效率,会分为Fetch线程和Consume线程,在consume完成之后,会提交offset;问题是:提交offset和consume仅有一个失败怎么办?
二:kafka消费的三种语义
1.At more once 至多一次,即消息可能会有丢失的情况
这种语义,很难被接受,网络故障、主副本选举、超时等因素就可能造成这种现象,而且若没这方面的意识,日志可能都不会打印,人工补偿都没法做到,造成这种现象的原因有:
a) 生产者:(很多参数可以影响,挑几个重点的)
异步调用,并没有设置回调函数;
ack=0,不等Broker确认就继续发送消息;
ack=1,等待leader确认后再发送消息,若follower没有跟上, 且leader挂掉,再选举将丢失
retries=0,不重试,或者重试之后,仍旧失败,不考虑重试队列或者人工补偿
b) 消费者
设置为自动提交,时间间隔设置的较短,且不手动提交offset;前文说到,Consumer分为Fetch和Consume两步,自动提交的offset是Fetch的,所以提交的最高offset的message还未处理;
2.At lease once 至少一次,即消息可能会有重复的现象发生
这种语义,被实现的较多,往往Consumer会拉到重复的message,再去在cache中做一层去重的处理,然后实现Exactly Once,至少在0.11之前未实现kafka事务之前;
a) 生产者
ack=ALL/-1,即等待In-sync的follower确认,才继续发送;
且retries > 1,且还是失败了之后,要有重试队列、死信队列、人工补偿的方案;
b)消费者 :关闭自动提交,并每次手动提交offset
3.Exactly once 正好一次,消息不多不少,需要一些外部条件辅助
a) 在At least once 的基础上,在业务方做幂等或者去重,比如redis去重,或业务上幂等;
b) 在At least once 的基础上,将offset和处理的结果组成一个原子事务,但这种方法,我个人觉得引入了更多的复杂性,参考 https://cloud.tencent.com/developer/article/1368989
c) 上面保证了不出错的情况下的,出错的情况下,需要重试队列、死信队列进行补偿;
d) kafka的0.11版本之后,提供了事务,利用事务可以实现;
三:重试队列(解决Consumer失败,同时不阻塞消费,针对少量失败)
1.实现原因
kafka中没有实现重试队列和死信队列的功能,但是由于当前的message的offset如果不提交,就会阻塞后续的消费,所以需要预留失败的message补偿的机制;实现方法有几种:
2.本地队列
用本地队列去控制,设置在定时器中,给任务设置30s,5min,30min三次重试的机会,如果不行,持久化到DB中,进行人工干预,当然报警、日志都要跟上; 优点:逻辑简单、实现简单,缺点:需要一些机制保证本地cache的可靠性,比如加hook预防服务更新,但是这样仍不能完全解决,还要面临初始化重试队列、宕机来不及调用hook等问题;
3.换RocketMQ、RabbitMQ,或者修改kafka实现
这个代价略大,而且这种不太受我们控制,很多消息队列的选型是已经固定的;修改kafka实现也不可能;
4.参考RocketMQ的思路,失败后直接放入新的topic:Retry+topic
这种思路也面临很大的问题:就是kafka没有实现延时的功能,那么新的message可能瞬时就被消费了,但是这个时候导致失败的原因,比如DB连接、网络问题没有解决,很快尝试几次之后,就进到死信队列了;
还有一种是《深入kafka》一书中也讲了一些方法,但是都需要改动kafka的内部实现,这个不太适合小型项目;
5.失败后直接放入新的topic,Redis实现延时功能
redis是很普遍的组件,而且对于少量失败、且对重试时间要求没那么严格的情况下,redis很适合,redis的持久化、哨兵之类的,对可靠性保证的还是很不错的;
留一篇文章,留着回忆redis的时候,再写吧
https://www.jianshu.com/p/3142f4092936
网友评论