前言:
MQ简介、特点、使用场景
RocketMQ简介及主流消息队列选型技术比较
- RocketMQ简介:
RocketMQ是阿里出品,Java语言编写的,历经多次双十一大促考验,它的性能、稳定性和可靠性都是值得信赖,每秒钟大概能处理几十万条消息,采用发布订阅模式
。源代码相对也比较容易读懂,也容易对 RocketMQ 进行扩展或者二次开发。RocketMQ 对在线业务的响应时延做了很多的优化,大多数情况下可以做到毫秒级的响应。比如交易系统和金融系统,很在意响应时延,那应该选择使用 RocketMQ。另,RocketMQ采用自研的协议,不支持 AMQP 协议等任何主流协议
基础
技术架构
四大组件
- Producer:生产者
- Consumer:消费者
- NameServer:简化版路由注册中心,其角色类似Dubbo中的zookeeper
- BrokerServer:Broker主要负责消息的存储
工作流程
基础概念
- Topic:主题 可以理解为一级分类,比如订单类消息
Topic是一个逻辑上的概念,实际上在每个broker上以queue的形式保存,也就是说每个topic在 broker上会划分成几个逻辑队列(这些逻辑队列=queue),每个逻辑队列保存一部分消息数据
- Tags: 消息标签 可以理解为二级分类,比如手机订单
- Topic 分片:一个Topic在一个Broker上的子集定义为一个Topic分片
- Queue:上文说了broker上会划分成几个逻辑队列,这些逻辑队列就是queue。
每个queue中存储多条消息(Message),且同一queue中的消息是有先后顺序的
queue是消费者消费的基本单元,queue越多,消费速度越快。
- Message:生产者生产的消息
- Message的属性如下:
- topic:消息主题
- tag :消息 TAG ,消费者消费消息时,用于同一Topic下消息的过滤
- keys: Message 索引键,用来快速搜索消息
- waitStoreMsgOK:消息发送时是否等消息存储完成后再返回
安装部署
集群搭建的几种方式
- 单Master模式:
这种方式风险较大,一旦Broker重启或者宕机时,会导致整个服务不可用。不建议线上环境使用,可以用于本地测试
- 多Master模式
一个集群无Slave,全是Master,例如2个Master或者3个Master,这种模式的优缺点如下:
优点:配置简单,单个Master宕机或重启维护对应用无影响,在磁盘配置为RAID10时,即使机器宕机不可恢复情况下,由于RAID10磁盘非常可靠,消息也不会丢(异步刷盘丢失少量消息,同步刷盘一条不丢),性能最高;
缺点:单台机器宕机期间,这台机器上未被消费的消息在机器恢复之前不可订阅,消息实时性会受到影响。
- 多Master多Slave模式-异步复制
每个Master配置一个Slave,有多对Master-Slave,HA采用异步复制方式,主备有短暂消息延迟(毫秒级),这种模式的优缺点如下:
优点:即使磁盘损坏,消息丢失的非常少,且消息实时性不会受影响,同时Master宕机后,消费者仍然可以从Slave消费,而且此过程对应用透明,不需要人工干预,性能同多Master模式几乎一样;
缺点:Master宕机,磁盘损坏情况下会丢失少量消息。
- 多Master多Slave模式-同步双写
每个Master配置一个Slave,有多对Master-Slave,HA采用同步双写方式,即只有主备都写成功,才向应用返回成功,这种模式的优缺点如下:
优点:数据与服务都无单点故障,Master宕机情况下,消息无延迟,服务可用性与数据可用性都非常高;
缺点:性能比异步复制模式略低(大约低10%左右),发送单个消息的RT会略高,且目前版本在主节点宕机后,备机不能自动切换为主机。
- Dledger集群(推荐)
RocketMQ-on-DLedger Group 是指一组相同名称的 Broker,至少需要 3 个节点,通过 Raft 自动选举出一个 Leader,其余节点 作为 Follower,并在 Leader 和 Follower 之间复制数据以保证高可用。
RocketMQ-on-DLedger Group 能自动容灾切换,并保证数据一致。
RocketMQ-on-DLedger Group 是可以水平扩展的,也即可以部署任意多个 RocketMQ-on-DLedger Group 同时对外提供服务
Dledger快速搭建
Dledger集群部署
部署常见配置:请参考本文第8节最佳配置
注册发现(NameServer-注册中心)
- 产生背景
解决消息生产者如何知道消息要发往哪台Broker服务器的问题
解决Broker服务器宕机了,生产者在不重启服务即可感知并切换到可用服务的问题
消息发送(producer-生产者)
消息发送流程
- Broker启动时,Broker向NameServer提交注册信息
- 客户端调用producer发送消息,先从NameServer获取该topic的路由信息(本地有缓存会先查询缓存),从NameServer返回的路由信息,包括topic包含的queue列表和broker列表
- Producer端根据消息选择器策略(可自定义:例如顺序发送),选出其中一个queue,组装请求
- producer向Broker发送请求,broker将消息保存。
- broker返回结果
消息发送方式(代码、示例)
- 同步:同步等待返回结果
- 异步:接收异步回调结果
- one-way:只管发送,不管返回结果
DefaultMQProducer
类是应用用来投递消息的入口,开箱即用,可通过无参构造方法快速创建一个生产者。主要负责消息的发送。
无法复制加载中的内容
消息存储(broker-代理)
消息存储组件
- CommitLog文件:保存消息的地方
- ConsumerQueue:消息消费队列文件,该文件可以看成是 CommitLog 关于消息消费的“索引”文件
消息存储流程
消息存储时首先将消息追加到内存,再根据配置的刷盘策略在不同时间进行写入磁盘CommitLog文件
消息存储方式
异步刷盘:消息存储到内存,便返回生产者成功
同步刷盘:消息存储到内存后,同步将消息存储到磁盘完成,才返回生产者成功
过期删除机制
默认存储3天,过期将删除
消息消费(consumer-消费者)
消费者集群的概念:使用相同Group ID的消费者属于同一个消费者集群。
- 集群消费:当使用集群消费模式时,消息队列RocketMQ认为任意一条消息只需要被集群内的任意一个消费者处理即可。适用于消费端集群化部署,每条消息只需要被处理一次的场景。此外,由于消费进度在服务端维护,可靠性更高。
- 广播消费:当使用广播消费模式时,消息队列RocketMQ版会将每条消息推送给集群内所有注册过的消费者,保证消息至少被每个消费者消费一次。实际应用场景不多,适用于每条消息需要被集群下的每个消费者处理的场景(例如,注册中心某台服务挂掉了,需要通知每一个节点)
消费消息的模式:推与拉:
- 推:
推模式指的是消息从 Broker 推向 Consumer,即 Consumer 被动的接收消息,由 Broker 来主导消息的发送。
- 推模式有什么好处?
消息实时性高, Broker 接受完消息之后可以立马推送给 Consumer。
对于消费者使用来说更简单,只需要等待消息推送过来。
- 推模式有什么缺点?
推送速率难以适应消费速率,推模式的目标就是以最快的速度推送消息,当生产者往 Broker 发送消息的速率大于消费者消费消息的速率时,随着时间的增长消费者那边可能就“爆仓”了,因为根本消费不过来啊。
- 总结:推模式难以根据消费者的状态控制推送速率,适用于消息量不大、消费能力强要求实时性高的情况下
- 拉:
拉模式指的是 Consumer 主动向 Broker 请求拉取消息,即 Broker 被动的发送消息给 Consumer。
- 拉模式有什么好处?
拉模式主动权就在消费者身上了,消费者可以根据自身的情况来发起拉取消息的请求。假设当前消费者觉得自己消费不过来了,它可以根据一定的策略停止拉取,或者间隔拉取都行。
拉模式可以更合适的进行消息的批量发送,基于推模式不知道消费者到底能不能处理这么多消息。而拉模式就更加合理,它可以参考消费者请求的信息来决定缓存多少消息之后批量发送。
- 拉模式有什么缺点?
消息延迟,毕竟是消费者去拉取消息,但是消费者怎么知道消息到了呢?所以它只能不断地拉取,但是又不能很频繁地请求,太频繁了就变成消费者在攻击 Broker 了。因此需要降低请求的频率,比如隔个 2 秒请求一次,你看着消息就很有可能延迟 2 秒了。
- 总结:RocketMQ 中的推模式其实是拉模式的包装,本质上都是拉模式。但RocketMQ本身对其做了优化(根据消息队列和消费者的数量做负载均衡、新消息来时及时唤醒等)避免了拉模式的缺点。
常见问题
生产者:采用同步发送+适当的重试策
Broker:采用同步刷盘,同步复制
消费者:消费成功再提交
- 如何解决重复消费(如何保证消费的幂等性)?
RocketMQ本身不保证消息不会被重复处理,需要消费者自己对业务做幂等性处理
- 最优配置
- HTTP静态服务器寻址(默认)
客户端启动后,会定时访问一个静态HTTP服务器,地址如下:http://jmenv.tbsite.net:8080/rocketmq/nsaddr,这个URL的返回内容如下:
192.168.0.1:9876;192.168.0.2:9876
客户端默认每隔2分钟访问一次这个HTTP服务器,并更新本地的Name Server地址。URL已经在代码中硬编码,可通过修改/etc/hosts文件来改变要访问的服务器,例如在/etc/hosts增加如下配置:
10.232.22.67 jmenv.taobao.net
推荐使用HTTP静态服务器寻址方式,好处是客户端部署简单,且Name Server集群可以热升级。
…………(待完善)
最佳配置
- topic与tag 的使用场景选择 ( topic不要开启自动创建)
- 配置参考(注册、生产、存储、消费配置调优等)
监控(控制台)
参考文献:
- RocketMQ 官方中文文档 (入门指引,知识讲解)
- RocketMQ 技术内幕-丁威 (原理讲解)
- RocketMQ 从入门到实战-丁威 (实战问题及解决方案)