七年零故障支撑双11的 RocketMQ,怎么做到的?( 三 )

ashMap 的 key ,把提取后的子表达式作为 HashMap 的 value ,这样每次过滤直接通过一次 hash 计算即可过滤掉绝大部分不适合的表达式,大大提高了过滤效率 。
优化效果该优化最主要降低了 CPU 计算逻辑,根据优化前后的性能情况对比,我们发现不同的交易集群中的订阅方订阅表达式复杂度越高,优化效果越好,这个是符合我们的预期的,其中最大的 CPU 优化有 32% 的提升,大大降低了本年度 RocketMQ 的部署机器成本 。
全新的消费模型 —— POP 消费背景RocketMQ的PULL消费对于机器异常hang时并不十分友好 。如果遇到客户端机器hang住,但处于半死不活的状态,与broker的心跳没有断掉的时候,客户端rebalance依然会分配消费队列到hang机器上,并且hang机器消费速度很慢甚至无法消费的时候,这样会导致消费堆积 。另外类似还有服务端Broker发布时,也会由于客户端多次rebalance导致消费延迟影响等无法避免的问题 。如下图所示:

七年零故障支撑双11的 RocketMQ,怎么做到的?

文章插图
 
当Pull Client 2发生hang机器的时候,它所分配到的三个Broker上的Q2都出现严重的红色堆积 。对于此,我们增加了一种新的消费模型——POP消费,能够解决此类稳定性问题 。如下图所示:
七年零故障支撑双11的 RocketMQ,怎么做到的?

文章插图
 
POP消费中,三个客户端并不需要rebalance去分配消费队列,取而代之的是,它们都会使用POP请求所有的broker获取消息进行消费 。broker内部会把自身的三个队列的消息根据一定的算法分配给请求的POP Client 。即使Pop Client 2出现hang,但内部队列的消息也会让Pop Client1 和Pop Client2进行消费 。这样就hang机器造成的避免了消费堆积 。
实现POP 消费和原来 PULL 消费对比,最大的一点就是弱化了队列这个概念,PULL 消费需要客户端通过 rebalance 把 broker 的队列分配好,从而去消费分配到自己专属的队列,新的 POP 消费中,客户端的机器会直接到每个 broker 的队列进行请求消费,broker 会把消息分配返回给等待的机器 。随后客户端消费结束后返回对应的 Ack 结果通知 broker,broker 再标记消息消费结果,如果超时没响应或者消费失败,再会进行重试 。
七年零故障支撑双11的 RocketMQ,怎么做到的?

文章插图
 
POP 消费的架构图如上图所示 。Broker 对于每次 POP 的请求,都会有以下三个操作:
  1. 对应的队列进行加锁,然后从 store 层获取该队列的消息;
  2. 然后写入 CK 消息,表明获取的消息要被 POP 消费;
  3. 最后提交当前位点,并释放锁 。
CK 消息实际上是记录了 POP 消息具体位点的定时消息,当客户端超时没响应的时候,CK 消息就会重新被 broker 消费,然后把 CK 消息的位点的消息写入重试队列 。如果 broker 收到客户端的消费结果的 Ack ,删除对应的 CK 消息,然后根据具体结果判断是否需要重试 。
从整体流程可见,POP 消费并不需要 reblance ,可以避免 rebalance 带来的消费延时,同时客户端可以消费 broker 的所有队列,这样就可以避免机器 hang 而导致堆积的问题 。
查看RocketMQ更多详情:https://www.aliyun.com/product/rocketmq?spm=5176.19720258.J_8058803260.342.44882c4aHmUC1H

【七年零故障支撑双11的 RocketMQ,怎么做到的?】


推荐阅读