RocketMQ基础知识扫盲

2019-06-18  本文已影响0人  刘一一同学

1. 简介

RocketMQ是一个队列模型的消息中间件,具有高性能、高可靠、高实时、分布式特点。主要具有以下作用:

例如,用户下单后,订单系统完成持久化处理,将消息写入消息队列,返回用户订单下单成功。库存系统订阅下单的消息,采用拉/推的方式,获取下单信息,库存系统根据下单信息,进行库存操作。

假如,在下单时库存系统不能正常使用,也不影响正常下单,因为下单后,订单系统写入消息队列就不再关心其他的后续操作了。

2. 相关角色

2.1 NameServer

NameServer的作用是注册中心,负责服务发现和路由,类似于Zookeeper。每个NameServer节点互相之间是独立的,没有任何信息交互。单台NameServer宕机不影响其他NameServer与集群,即使整个NameServer集群宕机,已经正常工作的Producer,Consumer,Broker仍然能正常工作,但新起的Producer、Consumer、Broker就无法工作。

2.2 Broker

Broker的作用是负责Topic消息存储、管理和分发等功能,Broker分为Master和Slave,一个Master可以对应多个Slave,但是一个Slave只能对应一个Master。Master和Slave的对应关系通过指定相同的BrokerName,不同的BrokerId来定义,BrokerId为0表示Master,非0表示Slave。

每个Broker与NameServer集群中的所有节点建立长连接,定时(每隔30s)注册Topic信息到所有的NameServer。NameServer定时(每隔10s)扫描所有存活的broker连接,如果NameServer超过2分钟没有收到心跳,则断开与broker的连接。

2.3 Producer

Producer与NameServer集群中的其中一个节点(随机选择)建立长连接,定期从NameServer获取Broker的路由信息,并向提供Topic服务的Master节点建立长连接,且定时向Master发送心跳。

Producer每隔30s(时间间隔由ClientConfig中的pollNameServerInterval配置决定)从NameServer获取所有Topic队列的最新数据,这意味着如果Broker不可用,Producer最多30s能够感知,在此期间内发往Broker的所有消息都会失败。

Producer每隔30s(时间间隔由ClientConfig中的heartbeatBrokerInterval配置决定)向所有关联的Broker发送心跳,Broker每隔10s扫描所有存活的连接,如果Broker在2分钟内每由收到心跳数据,则关闭与Producer的连接。

2.4 Consumer

Consumer与NameServer集群中的其中的一个节点(随机选择)建立长连接,定期从NameServer获取Topic路由信息,并向提供Topic服务的Master和Slave节点建立长连接,且定时向Master和Slave发送心跳。Consumer既可以从Master订阅消息,也可以从Slave订阅消息,订阅规则由Broker配置决定。

Consumer每隔30s从NameServer获取Topic的最新队列情况,这意味着Broker不可用时,Consumer最多需要30s才能感知。

Consumer每隔30s(时间由ClientConfig中的heartbeatBrokerInterval配置决定)向所有关联的Broker发送心跳,Broker每隔10s扫描所有存活的连接,若某个连接2分钟内没有发送心跳数据,则关闭连接,并向该ConsumerGroup的Consumer发出通知,Group内的所有Consumer重新分配队列,然后继续消费。

当Consumer得到Master宕机通知后,转向Slave消费,Slave不能保证Master的消息100%都同步过来,因此会丢失少量的消息。但是一旦Master恢复,未同步过去的消息会被最终消费掉。

集群消费模式:消费该Topic中部分Queue中的消息。
广播消费模式:消费该Topic下所有Queue中的消息。

消费者端的负载均衡,就是集群消费模式下,同一个ID的所有消费者实例平均消费该Topic的所有队列。假如Topic有6个队列,某个消费者ID启了2个消费者实例,那么每个消费者负责消费3个队列。

3. 刷盘策略

RocketMQ的所有消息都是持久化的,先写入系统PageCache,然后执行刷盘操作,可以保证内存与磁盘都有一份数据,访问时直接从内存读取。


刷盘策略
  1. 同步刷盘(SYNC_FLUSH):消息写入MQ返回成功状态时,此时消息已经被写入了磁盘。(消息首先写入内存PageCache后,立即通知刷盘线程,刷盘完成后,返回消息写入成功的状态)
  2. 异步刷盘(ASYNC_FLUSH):消息写入MQ返回成功状态时,消息只是被写入内存PageCache,当内存里的消息积累到一定程度时,将会触发写磁盘操作。

4. 复制策略

推荐:异步刷盘+同步复制

5. 如何保证消息顺序

例如,一个订单的顺序流程是:创建、付款、推送、完成。订单号做过取模运算再丢到selector中,selector保证同一个模的都会投递到同一条queue。即:相同订单号的 ---> 有相同的模 ---> 有相同的queue。

6. 如何解决重复消费问题

消费者端,可以采用日志表来记录已经处理成功的消息的ID,如果新到的消息ID已经在日志表中,那么这条消息就不在处理,从而保证幂等性。

7. 事务消息

7.1 RocketMQ三种事务状态

  1. CommitTransaction:消息提交,当消息状态为CommitTransaction,表示允许消费者允许消费当前消息.
  2. RollbackTransaction:消息回滚,表示MQ服务端将会删除当前半消息,不允许消费者消费。
  3. Unknown:中间状态,表示MQ服务需要发起回查操作,检测当前发送方本地事务的执行状态。

7.2 RocketMQ如何实现事务消息

  1. 生产者发送Prepare消息到Broker(事务消息的发送为同步方式)。
  2. Broker收到消息后,将消息写到Half TopicRMQ_SYS_TRANS_HALF_TOPIC),写入成功后给生产者返回成功响应。
  3. 生产者获取到该消息的事务ID后,开始执行本地事务。
  4. 本地事务执行成功后提交Commit,失败则提交Rollback。Broker收到Commit或Rollback消息后,将消息写到OP TopicRMQ_SYS_TRANS_OP_HALF_TOPIC)该Topic存放着Prepare消息对应的Commit/Rollback消息,Broker利用Half Topic和 OP Topic 可以计算出需要回查的消息。如果是Commit消息,Broker会将消息存到真正的Topic里,从而消费者可以正常消费消息。如果是Rollback消息,Broker会删除Prepare消息而不进行下发,然后生产者根据业务要求决定是否进行其他的回滚操作。
  5. 如果本地事务执行超时提交或者提交Unknow状态则会触发broker的事务回查功能。

7.3 事务消息投递的三个Topic

  1. Half Topic:用于记录所有的Prepare消息。
  2. Op(Operation ) Half Topic:记录已经提交了状态的Prepare消息。
  3. Real Topic:事务消息真正的Topic,在Commit后会才会将消息写入该Topic,从而进行消息的投递。

上一篇 下一篇

猜你喜欢

热点阅读