RocketMQ学习
说明:本资料中的内容及截图为本人在网络上学习时记录下的,侵权必删
第一章
介绍:解决分布式应用程序和应用程序之间的消息传递问题,解决项目之间的耦合和通讯问题。解决消息阻塞问题。
应用场景
-
应用解耦:系统的耦合性越高,容错性就越低
-
流量削峰:应用系统如果遇到系统请求流量的瞬间猛增,可能会将系统压垮
-
数据分发:通过消息队列可以让数据在多个系统直接进行流通
1 各角色介绍
- Producer:消息的发送者;
- Consumer:消息接收者;
消费者的两种模式:一种是DefaultMQPushConsumer和DefaultMQPullConsumer模式,这两种模式在字面上理解一个 是推送消息,一个是拉取消息,这是个误区,其实无论是拉还是推,其本质都是拉取消息。 - Broker:暂存和传输消息,事务的处理,消息的回查等;
- NameServer:管理Broker,相当于控制中心,记录Broker、Producer、Consumer等信息;
- Topic:区分消息的种类;一个发送者可以发送消息给一个或者多个TOpic;一个消息的接收者可以订阅一个或者多个Topic消息
- Message Quere:相当于是Topic的分区;用于并行发送和接收消息。
1.1 MQ的缺点
-
系统可用性降低
系统引入的外部依赖越多,系统稳定性越差。一旦MQ宕机,就会对业务造成影响。 -
系统复杂的提高
MQ的加入大大增加了系统的复杂度,以前系统间是同步远程调用,现在是通过MQ进行异步调用。
如何保证消息没有被重复消费?怎么处理丢失情况?怎么保证消息传递的顺序性。 -
一致性问题
A系统处理完业务,通过MQ给B、C、D三个系统发送消息数据,如果A系统、C系统处理成功、D系统处理失败,需要去保证消息数据处理的一致性。MQ的特点:
1.能够保证严格的消息顺序 2.能提供丰富的消息拉取模式 3.高效的订阅者水平能力 4.实时的消息订阅机制 5.支持事务消息 6.亿级消息堆积能力
1.2 集群特点
- NameServer是一个几乎无状态的节点,可集群部署,节点之间无任何信息同步。
- Broker部署相对复杂,Broker分为Master与Slave,一个Master可以应对多个Slave,但是一个Slave只能应对一个Master,Master与Slave的对应关系通过指定相同的BrokerName,不同的BrokerId来定义,BrokerId为0表示Master,非0表示Slave。Master也可以部署多个。每个Broker与NameServer集群中的所有节点建立长连接,定时注册Topic信息到所有非NameServer。
- Producer与NameServer集群中的其中一个节点(随机选择)建立长连接,定期从NameServer取Topic路由信息,并向提供Topic服务的Master建立长连接,且定时向Master发送心跳。Producer完全无状态,可集群部署。
- Consumer与NameServer集群中的其中一个节点(随机选择)建立长连接,定期从NameServer取Topic路由信息,并向提供Topic服务的Master、Slave建立长连接,且定时向Master、Slave发送心跳。Consumer既可以从Master订阅消息,也可以从Slave订阅消息,订阅规则由Broker配置决定。
2 RocketMQ集群模式
2.1 单个Master
这是一种风险比较大的集群方式,因为一旦Broker重启或宕机期间,将会导致这个服务不可用,因此是不建议线上环境去使用的。
2.2 多个Master
一个集群全部都是Master,没有slave,它的优缺点如下:
- 优点:配置简单,单个Master宕机或者是重启维护对应用没有影响的,在磁盘配置为RAID10时,即使机器宕机不可恢复的情况下,消息也不会丢失(异步刷盘丢失少量消息,同步刷盘则是一条都不会丢失),性能最高。
- 缺点:当单个Broker宕机期间,这台机器上未被消费的消息在机器恢复之前不可订阅,消息的实时性会受到影响。
2.3 多个Master多slave模式-异步复制
每个Master配置一个slave,有多对的Master-Slave,HA采用的是异步复制方式,主备有短暂的消息延迟,毫秒级别的(Master收到消息之后立刻向应用返回成功标识,同时向Slave写入消息)。优缺点如下:
- 优点:即使是磁盘损坏了,消息丢失的非常少,且消息实时性不会受到影响,因为Master宕机之后,消费者仍然可以从Slave消费,此过程对应用幽默,不需要人工干预,性能同多个Master模式机会一样。
- 缺点Master宕机,磁盘损坏的情况下,会丢失少量的消息。
2.4 多Master多Slave模式-同步双写
每个Master配置一个Slave,有多对的Master-Slave,HA采用的是同步双写模式,主备都写成功,才会向应用返回成功。
- 优点:数据与服务都无单点,Master宕机的情况下,消息无延迟,服务可用性和数据可用性都非常高。
- 缺点:性能比异步复制模式略低,大约10%左右,发送单个Master的RT会略高,目前主机宕机后,Slave不能自动切换为主机,后续会支持自动切换功能。
3 双主双从集群搭建
3.1 总体架构
3.2 集群工作流程
* 1)NameServer启动,NameServer起来后监听端口,等待Broker、Producer、Consumer连上来,相当于一个路由控制中心。
* 2)Broker启动,跟所有的NameServer保持长连接,定时发送心跳包。心跳包中包含当前Broker信息(IP+端口)以及存储所有的Topic信息。注册成功后,NameServer集群中就有Topic跟Broker的映射关系。
* 3)收发消息前,先创建Topic,创建TOpic时需要指定该Topic要存储在哪些Broker上,也可以在发送消息时自动创建Topic。
* 4)Producer 发送消息,启动时先跟NameServer集群中的其中一台建立长连接,并从NameServer中获取当前发送的Topic存在哪些Broker上,轮询从队列列表中选择一个队列,然后与队列所在的Broker建立长连接从而向Broker发消息。
* 5)Consumer 跟Producer类似,跟其中一台NameServer建立长连接,获取当前订阅Topic存在哪些Broker上,然后直接跟Broker建立连接通道,开始消费消息。
生产者发送消息
事务消息
生产者先提交预发送消息,如果将消息写入到HalfTopic(半提交),如果发送成功则再回调生产者执行本地事务的方法,执行成功,就将完整消息写入到OpTopic中再提交到RealTopic让消费者看到消息,回调方法如果执行失败或者超时、Unkonow状态是,则事务回查,若一直运行失败,则改事务代码或者环境有问题,需要重新检查或者写补偿代码完成事务。
| 序号 | IP | 角色 | 架构模式 |
| ------ | ------ | ------ |
| 1 | 192.168.0.102 | nameserver、brokerserver | Master1、Slaver2 |
| 2 | 192.168.0.103 | nameserver、brokerserver | Master2、Slaver1 |
Host添加配置
vim /etc/hosts
配置如下:
# nameserver
192.168.0.102 rocketmq-nameserver1
192.168.0.103 rocketmq-nameserver2
# broker
192.168.0.102 rocketmq-master1
192.168.0.102 rocketmq-slave2
192.168.0.103 rocketmq-master2
192.168.0.103 rocketmq-slave1
配置完成后,重启网卡
systemct1 restart network
conf文件说明:
2m-2s-async:双主双从异步模式
2m-2s-sync:双主双从同步模式
brokerClusterName=DefaultCluster //集群名
brokerName=broker-a //broker名
brokerId=0 //broker ID
deleteWhen=04 //什么时候删除不需要的数据 04 凌晨四点
fileReservedTime=48 //刷盘设置
brokerRole=SYNC_MASTER //broker角色
flushDiskType=ASYNC_FLUSH //刷盘策略
2m-noslave:双主模式
MASTER properties配置文件内容
#所属集群名字
brokerClusterName=rocketmq-cluster
#broker名字,注意此处不同配置文件填写的不一样
brokerName=broker-a
#0 表示Master, >0 表示Slave
brokerId=0
#nameServer地址,分号分割
namesrvAddr=rocketmq-nameserver1:9876;rocketmq-nameserver2:9876
#发送消息时,自动创建服务器不存在的topic,默认创建的队列数
defaultTopicQueueNums=4
#是否允许broker自动创建Topic,建议线下开启,线上关闭
autoCreateTopicEnable=true
#是否允许broker自动创建订阅组,建议线下开启,线上关闭
autoCreateSubscriptionGroup=true
#Broker 对外服务的监听端口
listenPort=10911
#删除文件时间点,默认凌晨四点
deleteWhen=04
#文件保留时间,默认48小时
fileReservedTime=120
#commitLog每个文件的大小默认为1G
mapedFileSizeCommitLog=1073741824
#ConsumeQueue每个文件默认存30w条,根据业务情况调整
mapedFileSizeConsumeQueue=300000
#destroyMapedFileIntervalForcibly=120000
#redeleteHangedFileInterval=120000
#检测物理文件磁盘空间
diskMaxUsedSpaceRatio=99
#存储路径
storePathRootDir=/usr/local/rocketmq/store
#commitLog存储路径
storePathCommitLog=/usr/local/rocketmq/store/commitLog
#消费队列存储路径
storePathConsumeQueue=/usr/local/rocketmq/store/consumequeue
#消息索引存储路径
storePathIndex=/usr/local/rocketmq/store/index
#checkpoint 文件存储路径
storeCheckpoint=/usr/local/rocketmq/store/checkpoint
#abort文件存储路径
abortFile=/usr/local/rocketmq/store/abort
#限制消息大小
maxMessageSize=65536
#flushCommitLogLeastPages=4
#flushCommitQueueLeastPages=2
#flushCommitLogThroughInterval=10000
#flushCommitQueueThoroughInterval=60000
#Broker 的角色
#- ASYNC_MASTER 异步复制Master
#- SYNC_MASTER 同步复制Master
#- SLAVE
brokerRole=SYNC_MASTER
#刷盘方式
#- ASYNC_FLUSH 异步刷盘
#- SYNC_FLUSH 同步刷盘
flushDiskType=SYNC_FLUSH
#checkTransactionMessageEnable=false
#发消息线程池数量
#sendMessageThreadPoolNums=128
#拉消息线程池数量
#pullMessageThreadPoolNums=128
SLAVE properties文件配置内容
#所属集群名字
brokerClusterName=rocketmq-cluster
#broker名字,注意此处不同配置文件填写的不一样
brokerName=broker-b
#0 表示Master, >0 表示Slave
brokerId=1
#nameServer地址,分号分割
namesrvAddr=rocketmq-nameserver1:9876;rocketmq-nameserver2:9876
#发送消息时,自动创建服务器不存在的topic,默认创建的队列数
defaultTopicQueueNums=4
#是否允许broker自动创建Topic,建议线下开启,线上关闭
autoCreateTopicEnable=true
#是否允许broker自动创建订阅组,建议线下开启,线上关闭
autoCreateSubscriptionGroup=true
#Broker 对外服务的监听端口
listenPort=11011
#删除文件时间点,默认凌晨四点
deleteWhen=04
#文件保留时间,默认48小时
fileReservedTime=120
#commitLog每个文件的大小默认为1G
mapedFileSizeCommitLog=1073741824
#ConsumeQueue每个文件默认存30w条,根据业务情况调整
mapedFileSizeConsumeQueue=300000
#destroyMapedFileIntervalForcibly=120000
#redeleteHangedFileInterval=120000
#检测物理文件磁盘空间
diskMaxUsedSpaceRatio=88
#存储路径
storePathRootDir=/usr/local/rocketmq/store
#commitLog存储路径
storePathCommitLog=/usr/local/rocketmq/store/commitLog
#消费队列存储路径
storePathConsumeQueue=/usr/local/rocketmq/store/consumequeue
#消息索引存储路径
storePathIndex=/usr/local/rocketmq/store/index
#checkpoint 文件存储路径
storeCheckpoint=/usr/local/rocketmq/store/checkpoint
#abort文件存储路径
abortFile=/usr/local/rocketmq/store/abort
#限制消息大小
maxMessageSize=65536
#flushCommitLogLeastPages=4
#flushCommitQueueLeastPages=2
#flushCommitLogThroughInterval=10000
#flushCommitQueueThoroughInterval=60000
#Broker 的角色
#- ASYNC_MASTER 异步复制Master
#- SYNC_MASTER 同步复制Master
#- SLAVE
brokerRole=SLAVE
#刷盘方式
#- ASYNC_FLUSH 异步刷盘
#- SYNC_FLUSH 同步刷盘
flushDiskType=ASYNC_FLUSH
#checkTransactionMessageEnable=false
#发消息线程池数量
#sendMessageThreadPoolNums=128
#拉消息线程池数量
#pullMessageThreadPoolNums=128
启动Broker集群
在192.168.0.102上启动master1和slave2
master1:
cd /usr/local/rocketmq/bin
nohup sh mqbroker -c /usr/local/rocketmq/rocketmq-all-4.7.0-bin-release/conf/2m-2s-sync/broker-a.properties &
slave2:
cd /usr/local/rocketmq/bin
nohup sh mqbroker -c /usr/local/rocketmq/rocketmq-all-4.7.0-bin-release/conf/2m-2s-sync/broker-b-s.properties &
在192.168.0.103上启动master2和slave2
master2:
cd /usr/local/rocketmq/bin
nohup sh mqbroker -c /usr/local/rocketmq/rocketmq-all-4.7.0-bin-release/conf/2m-2s-sync/broker-b.properties &
slave1:
cd /usr/local/rocketmq/bin
nohup sh mqbroker -c /usr/local/rocketmq/rocketmq-all-4.7.0-bin-release/conf/2m-2s-sync/broker-a-s.properties &
mq管理工具说明:https://www.cnblogs.com/zyguo/p/4962425.html
修改rocketmq=externals的地址为rocketmq.config,namesrvAddr=192.168.0.102:9876;192.168.0.103
修改完成后打包:mvn clean package -Dmaven.test.skip=true
4 消息发送样例
4.1 消息发送
- 1)发送同步消息
- 2)发送异步消息
- 3)单向发送消息
4.2 消费消息
- 1)负载均衡模式
- 2)广播模式
4.3 顺序消息
4.4 延时消息
RocketMQ目前并不支持任意时间的延时,需要设置几个固定的延时等级,从1s到2h分别对应着1到18
private String messageDelayLevel = "1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h";
4.5 批量消息
批量发送消息能显著提高传递小消息的性能。限制是这些批量消息应该有相同的topic,相同的waitStoreMsgOK,而且不能是延时消息。此外,这一批消息的总大小不应该超过4M。
4.6 过滤消息
4.6.1 SQL基本语法
4.6.2 消息生产者
4.7 事务消息
1) 事务消息发送及提交
- (1)发送消息(half消息)
- (2)服务端响应消息写入结果。
- (3)根据发送结果执行本地事务(如果写入失败,此时half消息对业务不可见,本地逻辑不执行)。
- (4)根据本地事务状态Commit或者Rollback(Commit操作生产消息索引,消息对消费者可见)
2)事务补偿
- (1)对没有Commit/Rollback的事务消息(pending状态的消息),从服务端发起一次”回查“
- (2)Producer收到回查消息,检查回查消息对应的本地事务状态
- (3)根据本地事务状态,重新Commit或者Rollback
- 其中,补偿阶段用于解决消息Commit或者Rollback发生超时或者失败的情况。
3)事务消息状态
事务消息共有三种状态,提交状态、回滚状态、中间状态
- TransactionStatus.CommitTransaction:提交事务,它允许消费者消费此消息。
- TransactionStatus.RollbackTransaction:回滚事务,它代表该消息将被删除,不允许被消费。
- TransactionStatus.Unknow:中间状态,它代表需要检查消息队列来确定状态。
第二章
1. 消息存储
1.1 存储方式
- 1)关系型数据库
- 2)文件存储
1.2 消息存储结构
RocketMQ消息的存储是由ConsumeQueue和CommitLog配合完成的,消息真正的物理存储文件是CommitLog,ConsumeQueue是消息的逻辑队列,类似数据库的索引文件,存储的是指向物理存储的地址。每个Topic下的每个MessageQueue都有一个对应的ConsumeQueue文件。
- CommitLog:存储消息的元数据
- ConsumerQueue:存储消息在CommitLog的索引
- IndexFile:为了消息查询提供了一种通过key或时间区间来查询消息的方法,这种通过IndexFile来查找消息的方法不影响发送与消费消息的主流程。
1.3 刷盘机制
1)同步刷盘
在返回写入成功状态时,消息已经被写入磁盘。具体流程是,消息写入内存的PAGECACHE后,立即通知刷盘线程刷盘,然后等待刷盘完成,刷盘线程执行完成后唤醒等待的线程,返回消息写成功的状态。
2)异步刷盘
在返回写成功状态时,消息可能只是被写入了内存的PAHECACHE,写操作的返回快,吞吐量大;当内存里的消息积累到一定程度时,同意触发写磁盘动作,快速写入。
3)配置
同步刷盘还是异步刷盘,都是通过Broker配置文件里的flushDiskType参数设置的,这个参数被配置成SYNC_FLUSH、ASYNC_FLUSH中的一个。
2 高可用性机制
RocketMQ分布式集群是通过Master和Slave的配合达到高可用性的。
Master和Slave的区别:在Broker的配置文件中,参数brokerId的值为了表明这个Broker是Master,大于0表明这个Broker是Slave,同时BrokerRole参数也会说明这个Broker是Master还是Slave。
Master角色的Broker支持读和写,Slave角色的Broker仅支持读,也就是Producer只能和Master角色的Broker连接写入消息;Consumer可以连接Matser角色的Broker,也可以连接角色的Broker来读取消息。
2.1 消费消息高可用性
2.2 消息发送高可用
消息主从复制
如果一个Broker组有Master和Slave,消息需要从Master复制到Slave上,有同步复制和异步复制两种方式。
1)同步复制
同步复制方式是Master和Slave均写成功后才反馈给客户端写成功状态;
在同步复制方式下,如果Master出故障,Slave上有全部的备份数据,容易恢复,但是同步复制会增大数据写入延迟,降低系统吞吐量。
2)异步方式
异步复制方式是只要Master写入成功即可反馈给客户端写成功状态。
在异步复制方式下,系统拥有低较延迟和较高的吞吐量,但是如果Master出了故障,有些数据因为没有被写入Slave,有可能会丢失。
3)配置
同步复制和异步复制是通过Broker配置文件里的brokerRole参数进行设置的,这个参数可以被设置成ASYNC_MASTER、SYNC_MASTER、SLAVE三个值中的一个。
4)总结
3 负载均衡
3.1 Producer负载均衡
Producer端,每个实例在发消息的时候,默认会轮询所有的message queue发送,以达到让消息平均落在不同的queue上。而由于queue可以散落在不同的broker,所以消息就发送到不同的broker下,如图:
3.2 Consumer负载均衡
在集群消费模式下,每条消息只需要投递到订阅这个topic的Consumer Group下的一个实例即可。RocketMQ采用主动拉取的方式拉取并消费消息,在拉取的时候需要明确指定哪一条message queue。
而每当实例的数量有变更,都会出发一次所有实例的负载均衡,这时候会按照queue的数量和实例的数量平均分配queue给每个实例。
默认的分配算法是AllocateMessageQueueAveragely,如下图:
另外一种平均算法是AllocateMessageQueueAveragelyByCirle,也是平均分摊每一条queue,只是以环状轮流分queue的形式,如下图:
3.2 广播模式
由于广播模式下要求一条消息需要投递到一个消费组下面所有的消费者实例,所以也就没有消息被分摊的说法。
在实现上,其中一个不同就是在consumer分配queue的时候,所以的consumer都分配到所以的queue。
4 消息重试
4.1 顺序消息的重试
4.2 无序消息的重试
1)重试次数
消息队列RocketMQ默认允许每条消息最多重试16次,每次重试的间隔时间如下:
注意:
一条消息无论重试多少次,这些重试消息的Message ID不会改变。
第三章
1 源码结构
3.2 广播模式
由于广播模式下要求一条消息需要投递到一个消费组下面所有的消费者实例,所以也就没有消息被分摊的说法。
在实现上,其中一个不同就是在consumer分配queue的时候,所以的consumer都分配到所以的queue。
4 消息重试
4.1 顺序消息的重试
4.2 无序消息的重试
1)重试次数
消息队列RocketMQ默认允许每条消息最多重试16次,每次重试的间隔时间如下:
注意:
一条消息无论重试多少次,这些重试消息的Message ID不会改变。
第三章
1 源码结构