23|延迟消息:怎么在 Kafka 上支持延迟消息?
延迟队列和延迟消息
- 深入了解
- 翻译
- 解释
- 总结
本文深入探讨了Kafka上的延迟消息实现方案,重点讨论了基于分区设置不同延迟时间的方案。通过创建delay_topic,并设置不同延迟时间的分区,利用延迟消费组和消费者实现消息转发到业务topic。文章还提到了该方案可能面临的rebalance和一致性问题,并提出了解决方案。此外,文章还介绍了基于MySQL的亮点方案,通过数据库存储实现延迟消息的转发。作者还对方案的优缺点进行了分析,指出了预先设定延迟时间和分区负载不均匀等问题。总体而言,本文为读者提供了对Kafka延迟消息实现方案的深入了解,涵盖了技术细节和解决方案,适合面试准备和实际应用参考。文章还提到了分区表、表交替、分库分表、批量操作等关键点,强调了分库分表与延迟消息结合的优势。文章最后提出了思考题,引发读者对不同方案的思考和讨论。
《后端工程师的高阶面经》,新⼈⾸单¥59
全部留言(20)
- 最新
- 精选
- 陈斌基于 MySQL 的亮点方案 中,延时消息的延时精度,取决于延时生产者的轮询频率。如果业务有要求在业务低谷期时延时精度要在0.5s内,那么轮询频率会高于每秒两次,那么就会限制并发上限。即并发越高,我感觉该方案的时间精度可能会越低。
作者回复: 盲生,你发现了华点,哈哈哈哈。是的,正常来说,并发很高的话,你可能一秒轮询就拿到几千条消息,这个时候你肯定来不及发完。‘ 优化的方法就是多线程,扫出来之后直接多线程来发送。这样的话发送比较快,就可以扫描更加频繁。
2023-08-29归属地:沙特阿拉伯2 - 第四死神开源版本在2022年7月20日 增加了 [RIP-43] Support Timing Messages with Arbitrary Time Delay
作者回复: 感谢提醒,倒是没想到!!!!果然是一年不学习,立马变垃圾。
2023-08-09归属地:北京2 - 一弦一柱思华年这里有个问题,关于delay-topic的:延迟消费者是每拉取一条数据就立马根据剩余时间睡眠吗,那这样的话消费速度远远跟不上生产速度吧。。假如我延迟时间是1小时,如果生产量稍微大一点,比如1000条消息,那后面的消息岂不是要等1000小时才能消费到,这样的话不是早就过期了吗,恐怕严重不符合用户使用预期。因此是否需要结合批量读来实现呢:根据业务场景并发量来看一次性拉取多少条合适,然后在延迟消费者里开启多线程睡眠为每条消息定时转发
作者回复: 首先纠正一个小细节,就是如果要是采用的是同一个分区固定延迟时间或者同一个 topic 固定延迟时间,那么你可以预期,如果第一个消息需要延迟一小时,后续的消息必然也是要延迟一小时的。因此你一小时到时之后,消费了第一条消息,第二条消息应该就差不多要到期了。你可以理解为流水,睡眠只是等第一滴水到来,之后都是源源不断的。
2024-01-16归属地:广东 - Geek_728b54老师好,在“分区设置不同延迟时间”方案中,如果其中一个消费者宕机和重启,这时候会不会触发整体的重平衡协议?
作者回复: 这是有可能的。但是你可以手动指定分区,并且在代码里面直接写死如果不是你预期的分区,你就忽略。那么在一个节点宕机之后,即便这个分区被分配给了别的消费者,因为别的消费者不会处理这个分区的消息,所以只有等到你本来宕机的节点重新恢复之后,这个分区的消息才会被处理。
2023-12-29归属地:北京 - sheep有个问题,“分区设置不同延迟时间”这里,消费者获取到指定消息之后,要延迟一定时间后,才能继续处理并提交信息吗。那这里,消费者获取到这个消息后,我启动一个协程来进行延迟和处理,是不是就能解决rebalance问题了呢?但是会有数据一致性的问题吧?比如这个协程处理异常或者服务宕机了,此时消息还没有处理完毕,就先前已经被提交了?
作者回复: 对,有一致性问题。比如说你启动 goroutine 之后,我节点和 Broker 失去联系了,一样会 rebalance。除非你说,我先提交,然后开 Goroutine 延迟处理,但是这样就会丢失。
2023-12-06归属地:广东 - 建涛涛涛、ᕕ( ᐛ )ᕗ请问一下老师, kafka + mysql 做随机时间的方案里, 既然都上mysql了。 还要kafka做什么? 只用 mysql, 然后轮询不就搞定了吗。
作者回复: 有一个 Kafka 在前面挡着,可以保护住 mysql。直接用的话,mysql 不一定撑得住那么大的并发。 另外一方面则是,客户端那边可能不希望和 mysql 打交道,而是希望说直接和 Kafka 打交道,然后 Kafka 后面你们怎么搞,就随便。
2023-11-29归属地:广东 - Geek_9affadmysql的方案可以替换成 Redis中有序集合的score来完成吧
作者回复: 可以的。Redis 高可用的话,可以不用 MySQL 的
2023-09-20归属地:山东 - itschenxiang老师你好。我这里有两个疑问哈: 1)分区设置不同延迟时间-rebalance 问题中,提出“暂停消费,睡眠一段时间 t”,这里前提是先消费到的消息先达到超时时间点吗? 2)分区设置不同延迟时间-一致性问题,这里是不是可以使用kafka的extract once,使用事务来进行转发控制呢,感觉这就是典型的使用场景?
作者回复: 1. 对的,因为你同一个分区,延迟时间都是一样的。 2. 这个我倒是没尝试过,但是你可以试试,看起来应该没啥问题。
2023-09-17归属地:广东2 - Geek8004mysql这个亮点方案,延迟发送者去高频率扫表,假如有16个topic对应16个库,每个库8张表,假设每个表每天产生50万数据,每次遍历索引或者是扫全表,性能会不会很差呀,大概要多久呀
作者回复: 不是遍历。它扫描就是用下次发送时间在下一秒的。每次就是取出来一秒,当然你也可以取出来十秒,但是要小心时间准确度。 性能的话,其实也没那么差,你保持一个线程扫描一张表,然后扫出来的数据可以开启多线程处理。
2023-09-01归属地:中国香港 - Geek8004老师,秒杀场景中,用户创建了未付款的订单,发了一条30min超时未支付取消订单的消息.在设置不同的延时分区这个方案里面,假如此时用户30分钟已经已经支付了,订单状态已经变成了已支付.但是30分钟到期了未付款的消息收到了,此时应该怎么办? 是不是用状态机? 状态只能往大的方向更改? 还是应该怎么处理呢?例如去把MQ里面的未支付的超时消息删除? 我觉得应该是判断当前订单的状态,如果是已支付或者已取消,那业务方就丢弃这个超时未支付的消息?
作者回复: 就是我提到的,当你要处理这个消息的时候,你要先确保它还是处于一种未支付的状态。 最简单的做法就是加分布式锁,检测状态,然后决定要不要丢弃消息。高级一点的就是用乐观锁。
2023-09-01归属地:中国香港