RocketMQ

分布式MQ

  1. Broker 消息中转者,负责存储消息,转发消息
  2. Producer 生产者
  3. Consumer 消费者
  4. Nameserver 分布式中心,维护Broker、状态保持
  5. Topic 消息主题
  6. Group 消费组

一些特性&问题

  1. 存在且不解决消息重复问题。
  2. RocketMQ通过轮询所有队列的方式来确定消息被发送到哪一个队列(负载均衡策略)
    Producer发送消息失败,会自动重试,可以设置最大重试次数和最长重试时间。

持久化消息

  1. consume queue是消息的逻辑队列,指定消息在commit log上的位置。
  2. 按照消费端GroupName来分组重试队列,消费失败,发往重试队列。
  3. 按照消费端GroupName来分组死信队列,无法投递,发往死信队列。
  4. Consume Queue的存储单元:CommitLog Offset,Size,Message Tag Hashcode。
  5. CommitLog的消息存储单元长度不固定,文件顺序写,随机读。单broker上被所有queue共享。

消息查询

  1. 根据MessageId查询,解析Broker地址和Commit Log偏移地址。
  2. 根据MessageKey,根据key的hashcode对slotNum取模得到槽位置,根据slotValue查找索引项列表最后一项,遍历索引项列表返回查询时间范围内的结果集。
  3. 正常消息消费流程:生产者发送消息,消息从socket进入java heap,进入pagecache(物理内存),同时异步线程flush disk,消费者拉消息,消息直接从pagecache转入socket,不过java heap。 异常消费情况:socket访问了虚拟内存,产生缺页中断,引发磁盘IO,从disk load到pagecache再到socket。

消息订阅

  1. 消费端主动拉取
  2. 消费端负载均衡:平均分配、消费端配置
  3. 消费端Push模式通过长轮询的模式实现。broker收到pull时,队列无数据,broker阻塞请求直到有数据传递或超时。

其他特性

  1. 定时消息
  2. 消息的刷盘策略
  3. 主动同步策略:同步双写、异步复制
  4. 海量消息堆积能力
  5. 高效通信

最佳实践

  1. 一个应用使用一个Topic,消息子类型使用tags标识,方便消费者过滤
  2. 消息唯一标识设置到keys字段
  3. 消息日志,要打印sendresult和key字段
  4. 若想不丢失消息,要有消息重发机制
  5. 消费端处理消息的业务逻辑保持幂等性
  6. 尽量使用批量方式消费,提高消费吞吐
  7. 保证每条消息都有唯一编号且保证消息处理成功与去重表的日志同时出现
  8. 优化消息消费过程
  9. 线上关闭autoCreateTopicEnable

设计相关

设计假定

  1. 每台PC机器都可能宕机不可服务
  2. 任意集群都可能处理能力不足
  3. 最坏的情况一定会发生
  4. 内网环境需要低延迟来提供最佳用户体验

关键设计

  1. 分布式集群化
  2. 强数据安全
  3. 海量数据堆积
  4. 毫秒级投递延迟(推拉模式)

CAP分别代表一致性(Consistency),可用性(Availability),分区容忍性(Partition tolerance)

现存问题

  1. 各语言sdk支持不足,目前只有Java、C++、.NET
  2. 支持TCP、JMS协议,但文档不足
  3. 近期有引擎层面的大版本变更,使用老版本会有风险