一.消息中间件
1.1消息中间件本质
一次RPC变成两次RPC、内容存储和择机投递;基于消息的通信模式,从关注处理到关注通知。
1.2 消息中间件的使用场景
解耦是消息中间件解决的最本质问题,核心业务只关心通知,不关心处理结果
可以用消息中间件实现微服务之间状态的最终一致性(只是理论上的,实际集群环境相当恶劣,宕机和假死频繁发生)
微服务之间消息的订阅和发布及集群消息
缓冲高并发请求洪峰,解决微服务机器网卡短板以及微服务db资源连接存在上限的问题
二.Rocketmq消息中间件
2.1Rocketmq物理集群架构
2.2 Rocketmq逻辑结构
Producer Group可以标识一类Producer,发送分布式事务消息时,如果Producer意外宕机,Broker会主动回调Producer Group内任意一台机器来确认事务状态。
2.3 Rocketmq功能特性剖析
2.3.1 单机支持 1 万以上持久化队列
单机支持1万以上的持久化队列的方案,尽量让队列轻量化,让单个队列消息负载均衡;对磁盘访问串行化,避免磁盘竞争,导致I/O等待超时。
方案的缺陷:
单机系统配置
中内存。
读变成顺序跳跃方式,而顺序跳跃方式读较完全的随机读性能会高 5 倍以上。
2. 由于Consume Queue 存储数据量极少,而且是顺序读,在 PAGECACHE 预读作用下,Consume Queue 的读性能几乎与内存一致。
3. Commit Log 中存储了所有的元信息,包含消息体,只要Commit Log在,消息就不会丢失。
2.3.2 刷盘策略
异步刷盘
测试机器顺序写文件,速度可以达到 300M 每秒左右,而线上的网卡一般都为千兆
网卡,写磁盘速度明显快亍数据网络入口速度,可以做到先写内存,后台线程异步刷盘持久化。如果遇到消息洪峰,写入消息到 PAGECACHE 时,如果内存不足,则尝试丢弃干净的 PAGE,腾出内存供新消息使用,策略是 LRU 方式。如果干净页不足,此时写入PAGECACHE会被阻塞,系统尝试刷盘部分数据,大约每次尝试32个PAGE。
同步刷盘
写入 PAGECACHE 后,线程等待,通知刷盘线程刷盘;刷盘线程刷盘后,唤醒前端等待线程,可能是一批线程;前端等待线程向用户返回成功
2.3.3 顺序消息
一个很简单的业务场景:
上游业务单实例Producer发送了消息Message1(订单创建)、Message2(订单付款)和Message3(扣减库存成功),消息消费要保证严格的顺序;下游业务单实例Consumer接收消息,注意消息在网络传输过程中存在网络抖动(极端情况节点宕机,故障恢复需要时间)如何保证消费者方顺序的消费消息。
RocketMq局部顺序消息:因为考虑Broker性能问题,RocketMq只支持分区顺序消息,不能保证全局顺序消息,消费方靠添加MessageListenerOrderly监听器来保证订阅在同一分区上的消费者会严格的按照发送顺序消费消息,如果要保留集群的failover特性,突发节点宕机,就不能保证消息的分区顺序性了,这个就要求业务方做接口幂等或者接口合法性校验(如果流量路由到从节点,分区路由的策略就变了,消息会自动路由到其他分区,导致消息错乱了)。
2.3.4 事务消息
目前RocketMq是支持事务消息的:
其实RocketMq加入分组和单元的概念就是为事务消息做准备的
2.3.5 存储
2.3.5.1 RocketMq Consumer过程使用了零拷贝
三.Rocketmq消息中间件的最佳实践
见实例
四.rocketmq集群部署
4.1多Master多slave集群部署 异步复制
准备4台机器,172.16.5.129 172.16.5.130 172.16.5.133 172.16.5.134
master 172.16.5.129
nohup sh bin/mqnamesrv >mqnamesrv.out &
nohup sh bin/mqbroker -c $ROCKETMQ_HOME/conf/2m-2s-async/broker-a.properties &
master 172.16.5.130
nohup sh bin/mqnamesrv >mqnamesrv.out &
nohup sh bin/mqbroker -c $ROCKETMQ_HOME/conf/2m-2s-async/broker-b.properties &
slave 172.16.5.133
nohup sh bin/mqnamesrv >mqnamesrv.out &
nohup sh bin/mqbroker -c $ROCKETMQ_HOME/conf/2m-2s-async/broker-a-s.properties &
slave 172.16.5.134
nohup sh bin/mqnamesrv >mqnamesrv.out &
nohup sh bin/mqbroker -c $ROCKETMQ_HOME/conf/2m-2s-async/broker-b-s.properties &
4.2多master 多slave集群部署 同步复制
准备4台机器,172.16.5.129 172.16.5.130 172.16.5.133 172.16.5.134
master 172.16.5.129
nohup sh bin/mqnamesrv >mqnamesrv.out &
nohup sh bin/mqbroker -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker-a.properties &
master 172.16.5.130
nohup sh bin/mqnamesrv >mqnamesrv.out &
nohup sh bin/mqbroker -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker-b.properties &
slave 172.16.5.133
nohup sh bin/mqnamesrv >mqnamesrv.out &
nohup sh bin/mqbroker -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker-a-s.properties &
slave 172.16.5.134
nohup sh bin/mqnamesrv >mqnamesrv.out &
nohup sh bin/mqbroker -c $ROCKETMQ_HOME/conf/2m-2s-sync/broker-b-s.properties &
4.3多master
准备两台机器 172.16.5.134 172.16.5.135
master 172.16.5.134
nohup sh bin/mqnamesrv >mqnamesrv.out &
nohup sh bin/mqbroker -c $ROCKETMQ_HOME/conf/2m-noslave/broker-b.properties &
master 172.16.5.135
nohup sh bin/mqnamesrv >mqnamesrv.out &
nohup sh bin/mqbroker -c $ROCKETMQ_HOME/conf/2m-noslave/broker-a.properties &
4.4 单点Master
准备一台机器 172.16.5.135
master 172.16.5.135
nohup sh bin/mqnamesrv >mqnamesrv.out &
nohup sh bin/mqbroker $ROCKETMQ_HOME/conf/broker.conf &
4.5 rocketmq集群管理
sh mqadmin
##查看集群状态
sh mqadmin clusterList -n '172.16.5.129:9876;172.16.5.130:9876;172.16.5.133:9876;172.16.5.134:9876'
##查看broker状态
sh mqadmin
java -jar rocketmq-console-ng-1.0.0.jar --server.port=12581 —rocketmq.config.namesrvAddr='172.16.5.129:9876;172.16.5.130:9876;172.16.5.133:9876;172.16.5.134:9876'
五 消息队列选型
特性 | ActiveMQ | RabbitMq | RocketMq | Kafka |
---|---|---|---|---|
Producer-Consumer | 支持 | 支持 | 支持 | 支持 |
Publish-Subscribe | 支持 | 支持 | 支持 | 支持 |
API完整性 | 高 | 高 | 高 | 高 |
多语言支持 | 支持 Java优先 | 语言无关 | 只支持Java | 支持 Java优先 |
单机吞吐量 | 万级 | 万级 | 万级 | 十万级 |
消息延迟 | 微妙级 | 毫秒级 | 毫秒级 | |
高可用性 | 高(主从) | 高(主从) | 非常高(分布式) | 非常高(分布式) |
消息丢失率 | 低 | 低 | 理论上不会丢失 | 理论上不会丢失 |
消息重复性 | 业务控制 | 业务控制 | 业务控制 | |
参考文档完整性 | 高 | 高 | 高 | 高 |
提供快速入门 | 有 | 有 | 有 | 有 |
首次部署难度 | 低 | 低 | 低 | 低 |
社区活跃度 | 高 | 高 | 中 | 高 |
商业支持 | 无 | 无 | 阿里云 | 无 |
成熟度 | 成熟 | 成熟 | 比较成熟 | 成熟日志领域 |
特点 | 功能齐全被大量开源项目使用 | 服务端采用Erlang语言,由于Erlang语言的并发能力,性能好,服务端源码学习门槛高 | 分布式扩展设计,主从HA,支持上万个队列,支持PUSH和PULL双从消费模式,性能比较好,服务端使用java,源码学习门槛低 | 分布式扩展设计,支持分片,分组,服务端采用高效的函数式编程语言Scala,并发能力极强,源码学习门槛高。 |
支持协议 | OpenWire、STOMP、REST、XMPP、AMQP | AMOP | 自定义协议 | |
---|---|---|---|---|
持久化 | 内存、文件、数据库 | 内存、文件 | 磁盘文件 | 磁盘文件 |
负载均衡 | 支持 | 支持 | 支持 | 支持 |
管理界面 | 一般 | 好 | Admin命令以及rocketmq-console界面 | |
部署方式 | 独立和嵌入 | 独立 | 独立 | 独立 |
事务 | 支持 | 不支持 | 支持 | 支持 |
评价 | 优点:产品成熟,普及度比较高(非大规模场景),文档较多,学习成本低,支持协议比较多,多语言客户端缺点:大规模队列系统稳定性不好。 | 优点:普及度比较高,特别是金融和电商领域,Erlang并发性能极高,社区活跃度比较高,学习成本低,Spring和SpringBoot以及SpringCloud对RabbitMq的无缝支持缺点:Erlang学习成本高,集群不能动态扩展 | 优点:使用简单,在阿里巴巴已经大规模应用;性能非常好,Broker可以大量的堆积消息;支持多种消费,包括集群消费、广播消费等;支持集群动态扩展缺点:目前网络资源匮乏,阿里只开源了一个半残次品,比较稳定的目前还没有开源。 |
六 rocketmq分布式事务消息原理设计
具体可以查阅接下来的文章。