1. RocketMQ消息写入磁盘的方式:同步刷盘和异步刷盘
❑ 异步刷盘方式:在返回写成功状态时,消息可能只是被写入了内存的PAGECACHE,写操作的返回快,吞吐量大;当内存里的消息量积累到一定程度时,统一触发写磁盘动作,快速写入。
❑ 同步刷盘方式:在返回写成功状态时,消息已经被写入磁盘。具体流程是,消息写入内存的PAGECACHE后,立刻通知刷盘线程刷盘,然后等待刷盘完成,刷盘线程执行完成后唤醒等待的线程,返回消息写成功的状态。
同步刷盘还是异步刷盘,是通过Broker配置文件里的flushDiskType参数设置的,这个参数被配置成SYNC_FLUSH、ASYNC_FLUSH中的一个。
2. RocketMQ主从同步方式:同步复制和异步复制
如果一个Broker组有Master和Slave,消息需要从Master复制到Slave上,有同步和异步两种复制方式。
同步复制方式是等Master和Slave均写成功后才反馈给客户端写成功状态;
异步复制方式是只要Master写成功即可反馈给客户端写成功状态。
这两种复制方式各有优劣,在异步复制方式下,系统拥有较低的延迟和较高的吞吐量,但是如果Master出了故障,有些数据因为没有被写入Slave,有可能会丢失;在同步复制方式下,如果Master出故障,Slave上有全部的备份数据,容易恢复,但是同步复制会增大数据写入延迟,降低系统吞吐量。
同步复制和异步复制是通过Broker配置文件里的brokerRole参数进行设置的,这个参数可以被设置成ASYNC_MASTER、SYNC_MASTER、SLAVE三个值中的一个。
实际应用中要结合业务场景,合理设置刷盘方式和主从复制方式,尤其是SYNC_FLUSH方式,由于频繁地触发磁盘写动作,会明显降低性能。
通常情况下,应该把Master和Save配置成ASYNC_FLUSH的刷盘方式,主从之间配置成SYNC_MASTER的复制方式,这样即使有一台机器出故障,仍然能保证数据不丢,是个不错的选择。
3. 部分顺序消息
要保证部分消息有序,需要发送端和消费端配合处理。在发送端,要做到把同一业务ID的消息发送到同一个Message Queue;在消费过程中,要做到从同一个Message Queue读取的消息不被并发处理,这样才能达到部分有序。
4. 消息的Tag和Key
对一个应用来说,尽可能只用一个Topic,不同的消息子类型用Tag来标识(每条消息只能有一个Tag),服务器端基于Tag进行过滤,并不需要读取消息体的内容,所以效率很高。发送消息设置了Tag以后,消费方在订阅消息时,才可以利用Tag在Broker端做消息过滤。
其次是消息的Key。对发送的消息设置好Key,以后可以根据这个Key来查找消息。所以这个Key一般用消息在业务层面的唯一标识码来表示,这样后续查询消息异常,消息丢失等都很方便。Broker会创建专门的索引文件,来存储Key到消息的映射,由于是哈希索引,应尽量使Key唯一,避免潜在的哈希冲突。
Tag和Key的主要差别是使用场景不同,Tag用在Consumer的代码中,用来进行服务端消息过滤,Key主要用于通过命令行查询消息。
5. Consumer的负载均衡
- DefaultMQPushConsumer的负载均衡
DefaultMQPushConsumer的负载均衡过程不需要使用者操心,客户端程序会自动处理,每个DefaultMQPushConsumer启动后,会马上会触发一个doRebalance动作;而且在同一个ConsumerGroup里加入新的DefaultMQPushConsumer时,各个Consumer都会被触发doRebalance动作。
以AllocateMessageQueueAveragely策略为例,如果创建Topic的时候,把Message Queue数设为3,当Consumer数量为2的时候,有一个Consumer需要处理Topic三分之二的消息,另一个处理三分之一的消息;当Consumer数量为4的时候,有一个Consumer无法收到消息,其他3个Consumer各处理Topic三分之一的消息。可见Message Queue数量设置过小不利于做负载均衡,通常情况下,应把一个Topic的Message Queue数设置为16。
- DefaultMQPullConsumer的负载均衡
Pull Consumer可以看到所有的Message Queue,而且从哪个Message Queue读取消息,读消息时的Offset都由使用者控制,使用者可以实现任何特殊方式的负载均衡。
DefaultMQPullConsumer有两个辅助方法可以帮助实现负载均衡,一个是registerMessageQueueListener函数,registerMessageQueueListener函数在有新的Consumer加入或退出时被触发。另一个辅助工具是MQPullConsumerScheduleService类,使用这个Class类似使用DefaultMQPushConsumer,但是它把Pull消息的主动性留给了使用者。
6. 配置文件
Property Name | Default value | Details |
---|---|---|
listenPort | 10911 | listen port for client |
namesrvAddr | null | name server address |
brokerIP1 | InetAddress for network interface | Should be configured if having multiple addresses |
brokerName | null | broker name |
brokerClusterName | DefaultCluster | this broker belongs to which cluster |
brokerId | 0 | broker id, 0 means master, positive integers mean slave |
storePathCommitLog | $HOME/store/commitlog/ | file path for commit log |
storePathConsumerQueue | $HOME/store/consumequeue/ | file path for consume queue |
mapedFileSizeCommitLog | 1024 * 1024 * 1024(1G) | mapped file size for commit log |
deleteWhen | 04 | When to delete the commitlog which is out of the reserve time |
fileReserverdTime | 72 | The number of hours to keep a commitlog before deleting it |
brokerRole | ASYNC_MASTER | SYNC_MASTER/ASYNC_MASTER/SLAVE |
flushDiskType | ASYNC_FLUSH | {SYNC_FLUSH/ASYNC_FLUSH}. Broker of SYNC_FLUSH mode flushes each message onto disk before acknowledging producer. Broker of ASYNC_FLUSH mode, on the other hand, takes advantage of group-committing, achieving better performance. |
参考文献:
- 杨开元 2018 《RocketMQ实战与原理解析》 机械工业出版社 ISBN:9787111600251
- https://rocketmq.apache.org/docs/rmq-deployment/