说明

  1. Kafka没有实现延时队列、死信队列、也没有重试机制。但是Spring-Kafka 封装了消费重试和死信队列。
  2. 这个是伪需求,只是一道面试题,不要太较真。
  3. 文章介绍了两个方案,有什么出错的地方,麻烦大佬们指出来,再次先谢谢啦。

Kafka 如何实现延时队列

  • Kafka 如何实现延时队列
    • 首先,先讲一个常见的业务场景吧,我们对这个场景进行扩展。比如,一个订单场景,一个用户下单后,如果超过30分钟后还没付款,那么我们就要取消这个订单,这时候就可以用延时队列了。
    • 方案一:
      • 订单服务,用户下单就会生成一个新订单,然后把订单发送给kafka,因为kafka不支持延时队列,所以,我们自己做一个延迟服务,把kafka的订单消息发送给延时服务。
      • 这个延时服务,过了30分钟后就要把这个订单消息发送kafka,然后订单服务消费这个延迟消息,再做业务处理(判断用户是否付款,如果没有付款就取消订单)。
      • 至于这个延时服务,我们可以用Java的延时队列来做。
      • 需要注意的是,我们需要保证延时服务的相对的可靠性,需要做:
        • 延迟消息的消费者手动提交offset
        • 延迟消息的消费者要做幂等性处理(根据业务需要)
        • 延时服务做 集群
      • 问题:如果延时服务挂了,那么将会丢掉消息,即使做集群,也会丢失。比如,消息A发送给节点A,节点A挂了,消息A的数据就丢了。后续流量都打到节点B,也就是集群只是保证后续消息的可靠性。
      • 思考:如果一定要用这种方案,如何优化呢?
        • 前端上做文章,比如,前端也搞个计时器,如果超过30分钟,那么订单页面就不要显示。(虽然前端防君子不防小人,但是99.99%的用户都是君子,前端还是有用的)
        • 人工补偿,运维定时去扫描订单表,如果订单有些因为上诉问题带来未及时关闭的问题,那么运维可以手动关闭。
    • 方案二:
      • 不要延时服务,订单服务发送一个消息,发送一个消息给kafka,这个消息要添加时间信息:30分钟的时间戳。为了保证顺序性,指定一个key,这样能保证所有消息在同一个partition(同一partition有序)。
      • 然后订单服务,开启一个线程,一直轮询kafka,如果系统当前时间大于第一个消息的时间戳,那么就可以消费了。
      • 问题
        • 带来消息的积压,压力来到kafka这边。
        • 而且要轮询,消费者也要牺牲一点轮询的性能。
        • 降低吞吐量,因为指定了key,只使用了一个partition(为了保证消息在kafka内部的有序)。
      • 好处:解决了方案一的问题。
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐