11 | 无消息丢失配置怎么实现?
11 | 无消息丢失配置怎么实现?
讲述:胡夕
时长12:42大小10.17M
“消息丢失”案例
最佳实践
小结
开放讨论
赞 31
提建议
精选留言(138)
- 阳明2019-06-27总结里的的第二条ack=all和第六条的说明是不是有冲突
作者回复: 其实不冲突。如果ISR中只有1个副本了,acks=all也就相当于acks=1了,引入min.insync.replicas的目的就是为了做一个下限的限制:不能只满足于ISR全部写入,还要保证ISR中的写入个数不少于min.insync.replicas。
共 25 条评论91 - ヾ(◍°∇°◍)ノ゙2019-07-05新建分区丢失是因为没有offset就从lastest开始读取,可以改成没有offset的时候从ealiest读取应该就可以了共 9 条评论53
- 曹伟雄2019-06-30单个 Consumer 程序使用多线程来消费消息说起来容易,写成代码却异常困难,因为你很难正确地处理位移的更新,也就是说避免无消费消息丢失很简单,但极易出现消息被消费了多次的情况。 关于这个问题,老师能否提供个java代码的最佳实践? 谢谢!
作者回复: 写过一两篇,https://www.cnblogs.com/huxi2b/p/7089854.html, 但总觉得不太完美。如果你想深入了解的话,推荐读一下Flink Kafka Connector的源码
共 2 条评论27 - 陈国林2020-01-09老师好,请教一个问题,ack=1的时候,min.insync.replicas还会生效吗?或者说还有必要吗,感谢 🤝
作者回复: 不生效,min.insync.replicas只有在acks=-1时才生效
共 3 条评论23 - cricket19812019-06-27consumer改用"从最早位置"读解决新加分区造成的问题共 2 条评论22
- lmtoo2019-06-27最后一个问题,难道新增分区之后,producer先感知并发送数据,消费者后感知,消费者的offset会定位到新分区的最后一条消息?消费者没有提交offset怎么会从最后一条开始的呢?
作者回复: 如果你配置了auto.offset.reset=latest就会这样的
共 3 条评论21 - ban2019-08-03老师, 如果我有10个副本,isr=10,然后我配置ack=all,min.insync.replicas=5, 这时候这两个参数以谁为准,生产一个消息,必须是全部副本都同步才算提交,还是只要5个副本才算提交?
作者回复: min.insync.replicas是保证下限的。acks=all的含义是producer会等ISR中所有副本都写入成功才返回,但如果不设置min.insync.replicas = 5,默认是1,那么假设ISR中只有1个副本,只要写入这个副本成功producer也算其正常写入,因此min.insync.replicas保证的写入副本的下限。
共 7 条评论18 - redis2019-11-21你好胡老师,想问一下 kafka是在落地刷盘之后,同步副本成功后,才能会被消费吗?
作者回复: 其实,有可能在落盘之前就被消费了。能否被消费不是看是否flush到磁盘,而是看leader副本的高水位是否越过了该条消息
共 6 条评论15 - 永光2019-06-27看了评论区回答还是不太理解,第二条ack=all与第六条min.insync.replicas 怎样协调工作的,总感觉是有冲突的。 问题是: 第二条的“已提交”和第六条的“已提交”是同一个意思吗?如果是同一个意思,那定义为什么不一样呀?展开
作者回复: acks=all表示消息要写入所有ISR副本,但没要求ISR副本有多少个。min.insync.replicas做了这样的保证
共 6 条评论13 - 美美2019-11-24胡老师 还有一种消息重复的情况希望帮忙分析下。producer发送消息后,broker成功写入消息了,但是ack因为网络问题没有到达producer,生产者可能会重试发送这条消息。 这种问题如何避免重复消费呢
作者回复: 使用幂等producer
共 6 条评论12 - Andy2019-07-04留言中ISR是什么?
作者回复: In-Sync Replicas,这是一个副本集合,里面的所有副本都是和Leader副本保持同步的
共 2 条评论10 - 浪迹人生2019-11-01请问消息的createTimestamp 是在生产者服务器上生成的,还是在进入不同partition 后生成的?我能不能根据这个时间戳来判断不同分区的消息原始全局顺序?谢谢🙏
作者回复: 在生产者服务器上生成的。个人感觉不可以,毕竟每个producer服务器上的时钟不是实时同步的。事实上,用时钟来保证同步性是一件非常不靠谱的事情
共 4 条评论10 - 多襄丸2020-07-28老师,我针对您的提问思考并查阅了一下相关资料,说一下我的思考哈: 我们假设有且仅有一个producer只在这个consumer感知到之前,新的partition分区只写了那么几条记录,不会再有其他producer写数据到这个新的partition中。 新增partition的情况,rebalance时由于我们默认offset.auto.reset=lastest,因此在使用了这个默认配置之下,producer较consumer先感知到新的partition将数据发送到新的partition,而consumer之后才感知到这个consumer,此时由于这个新的partition的offset是第一次消费,没有已提交的offset,所以使用latest从最新的位移开始读取,也就是producer写入消息offset + 1的那个位置开始读取,因此也就读取不到数据。 latest:有提交位移就从提交位移开始处理,没有提交位移就从最新的位移开始处理。 earlist: 有提交位移就从提交位移开始处理,没有提交位移就从最早的位移开始处理。 current: 从当前的提交位移开始处理。 因此,碰到上述情况,我们可以使用seekToBegin从这个新分区的开始位置读即可。 我能想到的办法是,实现一个ConsumerRebalanceListener,重写onPartitionsAssigned方法,在这个方法里我们每次都从自己维护的数据库系统里取offset,能取到说明这个partition是之前就存在的,按已有的offset继续消费就可以了,没有取到的记录表示是新增的partition,那么就从0开始消费并且保存当前offset到数据库。不论是不是新的,都可以seek到指定的位置,只是我们有没有维护到这个partition的offset记录的区别。也就不用针对这个新分区指定offset.auto.rset=earlist了吧? 希望得到胡老师的交流哈~展开
作者回复: 我觉得是很好的办法。值得一试:)
共 3 条评论9 - 毛毛鸦2020-02-26老师好,第七条没太理解啊, replication.factor 和 min.insync.replicas为什么不能相等呢,假如都是2,不可以吗,挂掉一个副本还有一个副本可用啊。
作者回复: 没有说不可以相等。如果都是2,挂掉一个副本,producer也就无法写入了,因为不满足min.insync.replicas的要求了
共 2 条评论7 - 云师兄2019-09-20acks=all表示消息要写入所有ISR副本,但没要求ISR副本有多少个。min.insync.replicas做了这样的保证 如果min.insync.replicas的参数设置比实际的isr副本多,producer的消息必须阻塞等broker的isr数量达到min.insync.replicas才提交成功吗
作者回复: 嗯,是的。当然如果一直不成功,最终producer请求会超时
7 - 快跑2019-06-28老师,你好。仔细阅读文稿后,仍有一些困惑 1、如果只用 send()方法(fire and forget), 即使配置retries,producer也是不知道消息状态,是不会重试的。所以说配置retries,要搭配send(msg, callback),这么理解正确么? 2、配置了retries, producer是怎么知道哪条消息发送失败了,然后重试
作者回复: 1. 不是。如果配置了retries,即使调用send(msg)也是会重试的。这是Kafka producer自己实现的机制,不需要用户干预 2. Broker发送response给producer,里面会保存error信息以及那个(些)batch出错了
共 5 条评论7 - nightmare2019-06-28多线程消费这么确保手动提交offset管理不会丢失呢,期待老师给一个消费端最佳实践7
- Geek_9862892019-06-27设置 acks = all。表明所有副本 Broker 都要接收到消息,该消息才算是“已提交”。如果所有的Broker都要收到消息才能算作已提交,会不会对系统的吞吐量影响很大?另外这里的副本指的是不是仅仅是ISR?
作者回复: 就我碰到的实际场景,影响还是很大的。acks=all时,大部分的请求处理延时都花在了follower同步上。 是的,acks=all表明所有ISR中的副本都要同步。
6 - AA2019-06-27如果consumer改用"从最早位置"读解决新加分区造成的问题,那会不会导致旧的分区里的已被消费过的消息重新全部被消费一次
作者回复: 只要位移没有越界以及有提交的位移,那么就不会出现这种场景。
共 3 条评论6 - 明翼2019-06-27这个问题我想个办法就是程序停止再增加分区,如果不能停止那就找个通知机制了。请教一个问题min.insync.replicas这个参数如果设置成3,假设副本数设置为4,那岂不是只支持一台broker坏掉的情况?本来支持三台坏掉的,老师我理解的对不对
作者回复: 嗯嗯,是的。本来就是为了更强的消息持久化保证,只能牺牲一点高可用性了~~
共 3 条评论6