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

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

延迟列队和延迟消息

  • 延迟列队是一种特殊队列,里面每个元素都有过期时间,如果没过期去拿元素会被阻塞,元素过期时就会拿到这个元素。可以说拿到的永远是最先过期的元素
  • 延迟消息指基于消息队列的延迟队列。消息不是被立刻消费,一段时间后才会被消费。到时间前,消息一直都被存储在消息队列的服务器上

支持延迟消息的消息队列

  • RabbitMQ:通过启动插件rabbitmq_delayed_message_exchange实现延迟消息。就是实现了一个exchange,exchange控制消息什么时候被投递到队列里

案例

利用定时任务调度

  • 开发一个定时任务平台,相当于业务发送者注册了一个任务,这个任务就是30分钟后发送一条消息到kafka上。之后消费者就能消费了
  • 缺点:定时任务中间件支撑不了高并发

分区设置不同延迟时间

  • 关键角色是delay_topic、延迟消费组

    • deleay_topic的分区被用来接收不同延迟时间的消息
    • 延迟消费组按照分区数量创建消费者,每个消费者一个分区。消费者每次读取一个消息,等延迟时间到后转发给biz_topic
介绍
  • 我们的方案比较简单,创建一个delay_topic,这个topic有N个分区,每个分区设置不同延迟时间。创建一个消费组消费这个delay_topic,消费者读取到消息后,根据延迟时间等待。等待完后发送到真正的topic上
亮点1
  • rebalance问题:消费者睡眠了,睡眠期间不消费消息,kafka会判定消费者崩溃,触发rebalance。rebalance之后,等消费者恢复过来,会被随机分配到别的分区,等于白睡了
  • 解决方案:利用kafka的暂停功能确保不触发rebalance,睡眠结束后再恢复。kafka的暂停功能相当于拉去0条数据,不是不拉数据。还是会发出poll调用,让kafka认为消费者还活着
亮点2
  • 一致性问题:实际就是再问biz_topic是先提交还是先转发,要抓住关键字后提交来回答
  • 一致性问题解决起来需要业务方配合,我们逻辑是到了延迟时间,就先转发biz_topic,然后再提交。也就是说转发biz_topic后,提交失败,下次还可以重试,biz_topic可能收到两条同样的消息。这种场景下只能要求消费者做到幂等
优缺点
  • 优点:足够简单,容易实现

  • 缺点:延迟时间必须预先设定好、分区之间负载不均匀

    • 延迟时间必须预先设定好:不支持随机延迟时间
    • 分区之间负载不均匀:很多业务只需要延迟3min。1min、10min数据就很少,可能造成消息积压问题

基于MySQL的亮点方案

实践中最好放弃随机延迟时间,绝大多数时间都用不上随机延迟时间。可以通过调整业务来适配固定的延迟时间

介绍

方案关键点是创建一个delay_topic ,业务发送者把消息发到这个topic,消息带上延迟的时间。然后有一个延迟消费者 ,消费delay_topic中的消息,转储到数据库 。还有一个延迟发送者 ,会轮询 数据库中的消息,把到时间的消息转发到真正的biz_topic中,完成后延迟发送者把数据库状态更新成已发送,最后业务消费者消费biz_topic

怎么支撑住高并发
  • 分区表:根据并发量选择按月份、周分、天分。历史分区直接清理

  • 表交替:准备两个表交替查写,交替查询。比如今天用tab0,明天用tab1,用tab1时就清空tab0,但延迟不能超过一天

  • 分库分表:并发非常高时考虑,只需要按照biz_topic的名字来分库分表,还可以叠加分区表和表交替提高性能

    • 隐患:不同topic并发度不一样,导致不同库不同表的压力差异很大
    • 解决方案:不考虑消息有序性,可以考虑轮询插入。查找只会按照发送时间来找,所以随机插入都没问题
    • 消息有序性:要保持消息有序性可以在分库分表时,确保同一个biz_topic的消息在同一张表,并且delay_topic也是按照biz_topic区分的,那么就可以保证延迟消息转发到biz上跟被发送到delay是一样的

批量操作

  • 还可以利用批量操作减轻MySQL的压力。延迟消费者可以消费了一批数据再批量插入到数据库,然后再提交这一批消息。延迟发送者可以发送一批数据后,再批量把这些消息更新为已发送
  • 批量操作可能会使数据一致性问题更严重。只要消费者可以做到幂等就可以了,比如用唯一索引
相关推荐
计算机毕设定制辅导-无忧学长33 分钟前
Kafka 核心架构与消息模型深度解析(二)
架构·kafka·linq
计算机毕设定制辅导-无忧学长33 分钟前
Kafka 核心架构与消息模型深度解析(一)
分布式·架构·kafka
Hoking1 小时前
Kafka集群部署(docker容器方式)SASL认证(zookeeper)
docker·zookeeper·kafka
Mr Aokey1 小时前
Spring MVC参数绑定终极手册:单&多参/对象/集合/JSON/文件上传精讲
java·后端·spring
14L2 小时前
互联网大厂Java面试:从Spring Cloud到Kafka的技术考察
spring boot·redis·spring cloud·kafka·jwt·oauth2·java面试
predisw2 小时前
kafka consumer group rebalance
分布式·kafka
地藏Kelvin2 小时前
Spring Ai 从Demo到搭建套壳项目(二)实现deepseek+MCP client让高德生成昆明游玩4天攻略
人工智能·spring boot·后端
菠萝013 小时前
共识算法Raft系列(1)——什么是Raft?
c++·后端·算法·区块链·共识算法
长勺3 小时前
Spring中@Primary注解的作用与使用
java·后端·spring
小奏技术4 小时前
基于 Spring AI 和 MCP:用自然语言查询 RocketMQ 消息
后端·aigc·mcp