RocketMQ 是阿里开源的国产消息中间件,由于其集群相对比较成熟,能保证消息零丢失,所以在金融领域或交易系统中广泛使用。
基本架构
1. NameServer: 消息发送和消费都是直连的 nameServer,nameServer 负责跳转到对应的 broker 上对应的 queue。
2. broker:保存 queue 信息,并且还负责主从间数据同步、以及高可用。
消息模型
RocketMQ 采用 pull 的方式进行消费,好处是,消费速度可以由consumer 自行控制。
根据消费的方式分为:
-
broadcast:广播模式,订阅同一个 topic 的所有 consumer 都会收到相同的消息。
-
cluster:负载均衡模式,订阅同一个 topic 的所有 consumer 都会收到不同消息,这些消息的并集是该 topic 收到的所有消息。
消息过滤
针对某个 topic ,producer 和 consumer 还可以对消息打 tag 来达到消息过滤的功能。
消息可靠性
1. 消息的安全
RocketMQ 提供了同步和异步的消息刷盘机制, 如果无法容忍消息的丢失可以选择同步的方式进行刷盘,需要牺牲性能来换取。
比如涉及到金融的交易系统,线上环境就完全采用同步方式:
2. 消息的顺序
RocketMQ 实现为一个 topic 会创建多个 queue ,这就造成消息的乱序问题, 解决方法:
producer 发送时指定要发送的具体的 queue:
SendResult sendResult = producer.send(msg, new MessageQueueSelector() {
@Override
public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
Integer id = (Integer) arg;
int index = id % mqs.size();
return mqs.get(index);
}
}, orderId);
consumer 在消费时,也只消费固定的一个 queue 即可:
consumer.registerMessageListener(new MessageListenerOrderly() {
AtomicLong consumeTimes = new AtomicLong(0);
@Override
public ConsumeOrderlyStatus consumeMessage(List<MessageExt> msgs,
ConsumeOrderlyContext context) {
});
事务消息
事务消息是RocketMQ 的重要特征之一,是指 producer 能够将发送消息和本地事务操作作为一个事务处理的能力。
事务消息具体工作流程:
代码层面相对起来比价简单,producer 发送消息前,设置个 TransactionListener 回调即可。
public interface TransactionListener {
/**
* When send transactional prepare(half) message succeed, this method will be invoked to execute local transaction.
*
* @param msg Half(prepare) message
* @param arg Custom business parameter
* @return Transaction state
*/
LocalTransactionState executeLocalTransaction(final Message msg, final Object arg);
/**
* When no response to prepare(half) message. broker will send check message to check the transaction status, and this
* method will be invoked to get local transaction status.
*
* @param msg Check message
* @return Transaction state
*/
LocalTransactionState checkLocalTransaction(final MessageExt msg);
}
集群与可视化
1. 集群
生产环境,为了保证高可用,NameServer 和 broker server 都需要集群部署,集群内部采用主从结构搭建(比如文末界面展示2主2从)。
NameServer 集群: 每个 nameServer 都会存储完整的 broker server 的路由信息,只要有一个 NamerServer 实例正常,整个集群就能正常服务。实例间并不进行数据共享,broker 在启动时会向所有的 nameServer 进行注册。
Broker 集群:Master 负责消息的 RW, slave 只接收 R。实例间数据通过同步或异步的方式进行复制。
producer 集群:发送消息时,会选择对应 topic 下的一个 queue 发送,相同 producerGroup 的 producer 不同实例,可以处理事务消息的正确提交或者回滚消息(在一个 producer 提交了本地事务后宕机)。
consumer 集群:同一 consumerGroup 的需要订阅相同 topic(一个或多个) 的消息。是实现负载均衡和容错的重要概念。
根据上面的介绍,我们知道消息的发送与消费都是负载均衡的方式。
是否跨机器,取决于创建topic 的方式:可以在一个 broker 上创建 topic 也可以在集群上创建 topic。
2. 可视化
由第三方开源的 Rocketmq-console 是 rokcetmq 可视化的最佳工具。
通过界面查看 NameServer 集群:
通过界面查看 broker 集群:
创建 topic: (跨broker的)
查看topic 的消费者:
功能很强大,大家可以自己摸索。
如果觉得还不错的话,关注、分享、在看(关注不失联~), 原创不易,且看且珍惜~