【MQ】一套为海量消息和高并发热门消息,提供高可用精准延时服务的解决方案 ...

打印 上一主题 下一主题

主题 677|帖子 677|积分 2031

延迟消息假如利用延时交换机来实现,假如数据量过大,就会很占 CPU 资源,轻则时间误差大,重则 RabbitMQ 宕机
一、针对一个 RabbitMQ 节点

关键词:RabbitMQ,Redis ZSet,XXL-JOB,定时线程池
(1)利用队列+ ttl,将延迟消息根据 delay 的时间进行分级

比如两小时、一天,这两个级别:

  • 小于两天的消息直接放在延迟交换机
  • 两天到一天的交给 ttl 为两小时的队列
  • 别的的交给 ttl 为一天的队列
   值得注意的是无论是 ttl 还是 delay,都只能是 int 范例的整数,单位是 ms,差不多 49 天(有符号整型则是 24 天),以是凌驾这个时间的要额外处置惩罚哦!
  而两个 ttl 队列绑定同一个死信交换机,死信被咱们的服务处置惩罚后重新发送(delay - ttl,或者消息自己携带时间的信息,重新计算 delay),再根据新的 delay 判断前往哪里
   这里可行的缘故因由是,队列 + ttl 的 CPU 斲丧只用于队列头的那一条消息,在这里就可以生存很多消息
  ttl 队列还可以设置为惰性队列,而且因为延时这种队列假如不密集过期的话,速率的影响很小,存储的量却可以很大!
对于这个问题,RabbitMQ 这个插件更适合于 delay 比较匀称的情况,一样平常到这里就结束了,但是有个坑点,一个热门时间的延迟消息会一起进入延迟交换机
(2)对于热门时间的消息处置惩罚

可以在发送到延迟交换机之前,先监控其数目(可以用 Redis 实现一个计数器),控制在一个可控的量级,如 10W,在范围内则发送,否则

  • 存储起来,可以是 Redis 有序队列,或者利用 RabbitMQ 的优先级队列,但是要主动的获取消息而不是监听
  • 周期性的扫描(五分钟左右),监控 RabbitMQ 延时交换机的健康值,可以参加就参加(需要先执行的小的先参加)(也可以 delay 相同的同一种消息归并成一个,与监听器约定一下这种情况)
  • 但大概因为没及时扫描,导致新 delay ≤ 0,因此大概产生误差,我们可以将 delay 小于周期隔断的

    • 接受误差的范围内的不给予处置惩罚(你可以接受这五分钟的误差,那也行,不外要注意的是,这个消息的执行效果不应该收到这个误差的影响,需要包管终极同等性)
    • 直接本地延时任务、或者交给 Redis 做延时队列等等延时的技术,用于分担多出来的这一份数据量(反正就是天女散花,将这个任务分担给其他服务)

假如是一个热门时间,消息的 delay 都很接近,但其实经过多次周期性的扫描,这个热门时间的消息大部分都可以进入延时交换机,再用 Redis 在最后接近热门时间,“冲刺”的时候助 RabbitMQ 一臂之力
以上是单机情况下我能想到的最好方案了,世界上没有绝对完善的东西,你大概描述一个极度的场景依旧大概出现问题,因此你可以解决其本质缘故因由 “就是一个 MQ 处置惩罚不外来”
对于这种大数据量的情况,这一业务独享一个 RabbitMQ,减少 CPU 在其他业务的消耗
代码实现:https://github.com/CarefreeState/OKR-System4.0/tree/main/src/main/java/cn/bitterfree/api/mq
二、多个 RabbitMQ 节点相互扶持

因为集群针对的是队列中消息的同步,并不会同步延时交换机暂存的消息,这样不同的 RabbitMQ 去维护各自的延迟交换机就行了,让各个节点的延时交换机的数据量处在安全值范围内,之后到达队列再消息同步
   你大概说,那宕机了,岂不是丢失了
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

星球的眼睛

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表