后端工程师的高阶面经
邓明
前 Shopee 高级工程师,Beego PMC
6888 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 50 讲
后端工程师的高阶面经
15
15
1.0x
00:00/00:00
登录|注册

23|延迟消息:怎么在 Kafka 上支持延迟消息?

你好,我是大明。今天我们来讨论一个在消息队列面试中非常热的话题——延迟消息。
延迟消息在 Kafka 面试里面是非常热门的,其他消息队列多少也会问,但是不如 Kafka 问得频繁。因为 Kafka 不支持延迟消息是大家都知道的。但是偏偏 Kafka 又用得多,很多业务场景也要求使用延迟消息,因此面试的时候延迟消息就成了一个重要的考察点。
和之前的面试点不同,能把延迟消息的方案讲得清楚透彻的人就不多,更不要说刷亮点了。那么今天我就带你深入延迟消息,并且给出一个非常高级的方案。这个方案会涉及到分库分表,所以能帮助你把这些知识融会贯通。

延迟队列和延迟消息

延迟队列是一种特殊的队列。它里面的每个元素都有一个过期时间,当元素还没到过期时间的时候,如果你试图从队列里面获取一个元素,你会被阻塞。当有元素过期的时候,你就会拿到这个过期的元素。你可以这样想,你拿到的永远是最先过期的那个元素。
很多语言本身就提供了延迟队列的实现,比如说在 Java 里面的 DelayQueue。
这节课我们讨论的就是一种特殊形态的延迟队列,或者说是基于消息队列的延迟队列,也叫做延迟消息。具体来说,延迟消息是指消息不是立刻被消费的,而是在经过一段时间之后,才会被消费。在到时间之前,这个消息一直都被存储在消息队列的服务器上。上一节课,我就举了订单超时取消的例子,它就用到了延迟消息。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文深入探讨了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_9affad
    mysql的方案可以替换成 Redis中有序集合的score来完成吧

    作者回复: 可以的。Redis 高可用的话,可以不用 MySQL 的

    2023-09-20归属地:山东
  • itschenxiang
    老师你好。我这里有两个疑问哈: 1)分区设置不同延迟时间-rebalance 问题中,提出“暂停消费,睡眠一段时间 t”,这里前提是先消费到的消息先达到超时时间点吗? 2)分区设置不同延迟时间-一致性问题,这里是不是可以使用kafka的extract once,使用事务来进行转发控制呢,感觉这就是典型的使用场景?

    作者回复: 1. 对的,因为你同一个分区,延迟时间都是一样的。 2. 这个我倒是没尝试过,但是你可以试试,看起来应该没啥问题。

    2023-09-17归属地:广东
    2
  • Geek8004
    mysql这个亮点方案,延迟发送者去高频率扫表,假如有16个topic对应16个库,每个库8张表,假设每个表每天产生50万数据,每次遍历索引或者是扫全表,性能会不会很差呀,大概要多久呀

    作者回复: 不是遍历。它扫描就是用下次发送时间在下一秒的。每次就是取出来一秒,当然你也可以取出来十秒,但是要小心时间准确度。 性能的话,其实也没那么差,你保持一个线程扫描一张表,然后扫出来的数据可以开启多线程处理。

    2023-09-01归属地:中国香港
  • Geek8004
    老师,秒杀场景中,用户创建了未付款的订单,发了一条30min超时未支付取消订单的消息.在设置不同的延时分区这个方案里面,假如此时用户30分钟已经已经支付了,订单状态已经变成了已支付.但是30分钟到期了未付款的消息收到了,此时应该怎么办? 是不是用状态机? 状态只能往大的方向更改? 还是应该怎么处理呢?例如去把MQ里面的未支付的超时消息删除? 我觉得应该是判断当前订单的状态,如果是已支付或者已取消,那业务方就丢弃这个超时未支付的消息?

    作者回复: 就是我提到的,当你要处理这个消息的时候,你要先确保它还是处于一种未支付的状态。 最简单的做法就是加分布式锁,检测状态,然后决定要不要丢弃消息。高级一点的就是用乐观锁。

    2023-09-01归属地:中国香港
收起评论
显示
设置
留言
20
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部