《RockeMQ实战与原理解析》 学习笔记

第一章

1.1 消息队列的功能介绍

1.1.1 应用解耦

1.1.2 流量消峰

大部分应用系统在高峰时间段流量会猛增, 这个时候如果没有缓冲机制,不可能短时间内承受住大流量的冲击。利用消息队列,把大量的请求缓存起来,分散到相对长的一个时间段内处理,能大大提高系统的稳定性和用户提现。

1.1.3 消息分发

数据产生方将数据写入一个消息队列,数据使用方根据自己的需求订阅感兴趣的数据,各个团队订阅的数据可以重复,也可以不重复,互不干扰。

第二章 生产环境下的配置和使用

2.1 RocketMQ 各部分角色介绍

(1) Producer, Consumer, Broker, NameServer
(2) Producer, Consumer 从 NameServer 获得 Broker 的 信息。
(3) Broker 将 Routing Info 发给 NameServer。
(4) Producer 发送 消息 给Broker, Consumer 从Broker 接受消息。
(5) Topic: 发送和接收消息前, 先创建Topic, 针对某个Topic 发送接收消息。
(6) MessageQueue: 如果一个Topic 要发送或接收的消息量特别大,需要能够支持并行处理的机器来提高速度,这时候一个Topic 可以根据需要设置多个MessageQueue,MessageQueue 类似分区或Partition. 消息可以并行的向各个MessageQueue 发送,消费者也可以并行的从多个MessageQueue读取消息并消费

2.2 多机集群配置和部署

两台物理机,搭建双主,双从,无单点故障的高可用集群。 首先在两台机器上分别启动NameServer。然后分别启动一个Master角色的Broker 和一个Slave 角色的Broker, 并且互相为主备。

2.2.2 Broker配置文件参数配置介绍

(1) namsrvAddr = 192.168.100.131:9876;192.168.100.132:9876 namesrv 端口
(2) brokerName=broker-a
Broker 的名称, Master 和Slave通过相同的名称标识相互关系,说明某个Slave 是哪个Master 的Slave
(3)brokerId=0
一个master可以有多个Slave, 0 表示Master, 大于0 表示不同的Slave的ID。
(4)fileReservedTime=48
在磁盘上保存消息的时长,单位是小时,自动删除超时消息。
(5)deleteWhen=04
表明在几点做删除消息的动作, 默认是凌晨4点。
(6)brokerRole=SYNC_MASTER
brokerRole 有3种: SYNC_MASTER, ASYNC_MASTER, SLAVE。关键词SYNC和ASYNC表示Master和Slave之间同步消息的机制。SYNC表示当Slave和Master消息同步完成后,再返回发送成功的状态
(7)flushDiskType=ASYNC_FLUSH
表示刷盘策略,分别为SYNC_FLUSH, ASYNC_FLUSH。同步刷盘和异步刷盘。同步:消息真正写入磁盘后再返回成功。异步:消息写入page_cache 后就返回成功状态。
(8)listenPort=10911
Broker 监听的端口, 如果一台物理机器上启动了多个Broker, 则要设置不同的端口。

第三章 用合适的方式发送和接收消息

3.1 不同类型的消费者

3.1.1 DefaultMQPushConsumer

(1) DefaultMQPushConsumer 的三个参数:

  • GroupName:把多个Consumer 组织到一起,提供并发处理能力,GroupName 要和消息模式(MessageModel)配合使用。
  • NameServer的地址和端口号。
  • Topic: 需要提前创建。如果不需要消费某个Topic下的所有消息,可以指定消息的Tag进行消息的过滤, 比如 Conusmer.subscribe(“TopicTest”, “tag1||tage2”)。

(2) RocketMQ 支持的两种消息模式:Clustering 和 Broadcasting:

  • Clustering: 同一个ConsumerGroup(GroupName相同)里的每个Consumer 只消费所订阅的一部分内容,同一个ConsumerGroup里所有的Consumer消费的内容合起来是所订阅的Topic内容的整体,从而达到负载均衡。
  • Broadcasting; 同一个ConsumerGroup 里的每个Consumer 都能消费到所订阅的Topic的全部内容,也就是一个消息被分发多次,被多个Consumer消费。

(3)DefaultMQPushConsumer的处理流程

  • 通过“长轮询”方式达到Push效果,长轮询方式既有Pull的优点,有兼具Push方式的实时性。
  • Push 方式: 当Server端接收到消息后,主动把消息推送给Client端,优点是实时性高。缺点是:(1)首先加大了Server端的工作量,进而影响Server的性能。(2)如果客户端不能及时处理Server推送过来的消息,会造成各种潜在危险。
  • Pull 方式:Client 段循环的从Server段拉取消息,优点是:自己拉取到一定量消息后,处理妥当了再接着取。缺点是:拉取消息的时间间隔不好设置,间隔短就是忙等,间隔长Server段的消息没有被及时拉取。
  • 长轮询方式核心是–Broker 端HOLD 住客户端过来的请求一小段时间,在这个时间段内有新消息到达,就利用现有的连接返回给Consumer。通过 RequestHeader.setSuspendTimeoutMillis() 语句实现,默认设置是15秒。服务端接到客户端请求新消息的请求后,如果队列里没有消息,就会通过一个循环,每5秒检查下有没有消息。如果第三次检查,依旧没有消息,就返回NULL。如果等待的过程中,有新消息到达,就会立即返回给客户段。局限性:HOLD住Consumer 请求的时候需要占用资源,适合用在客户端连接数可控的场景。

(4) DefaultMQPushConsumer 的流量控制

  • 流量的控制。首先,每个MessageQueue都有一个快照类ProcessQueue保存这个MessageQueue 消息处理的状态, 比如当前消息堆积的个数,当前消息的总大小,消息的Offset的跨度。只要任何一个值超过设定的预设大小,就会过一段时间再去Broker拉去消息,从而达到流量控制的目的。
  • ProcessQueue对象主要内容是一个TreeMap和一个读写锁。 TreeMap 以Message Queue 的offeSet 为key, 消息的内容为Value, 保存MessageQueue中还未处理的消息。 读写锁控制对ProcessQueue的并发访问。

3.2 消息的生产者

不同的业务场景,需要生产者采用不同的写入策略:同步发送,异步发送,延迟发送,发送事务消息。

3.2.1 DefaultMQProducer

  • 发送消息的五个步骤: (1)设置Producer的GroupName (2)设置InstanceName。当一个JVM需要启动多个Producer的时候,通过设置InstanceName来区分。(3)设置发送失败重试次数。(4) 设置NameServer地址。(5) 组装消息并且发送
  • 消息发送返回状态:(1)Flush_DISK_TIMEOUT (2)FLUSH_SLAVE_TIMEOUT (3)SLAVE_NOT_AVAILABLE (4)SEND_OK

3.2.2 发送延迟消息

  • Broker 收到这类消息后,延迟一段时间在处理,使消息在规定的一段时间后生效。
  • 延迟消息使用方法是在创建Message对象时,调用setDelayTimeLevel(int level)。

3.2.3 自定义消息发送规则

  • 一个Topic 会用多个Message Queue, 如果使用Producer的默认设置,这个Producer会轮流向各个Message Queue 发送消息。Consumer 在消费消息时,会根据负载均衡策略,消息被分配到的Message Queue, 不进过特定的设置,某条消息被发送到哪个MessageQueue, 被哪个Consumer 消费是未知的。
  • 把同一类型的消息都发送到相同的Message Queue,使用 MessageQueueSelector。实现顺序消费, 见我的博客 《RocketMQ实现顺序消息》。

3.2.4 事务消息

  • 发送消息事件和其他事件需要同时成功或同时失败。
  • RocketMQ 采用两阶段提交的方式实现事务消息。
  • (1)发送方向Broker 发送 “待确认”消息(b 银行增加一万元)。
  • (2)Broker 将受到的 “待确认”消息持久化成功,向发送方回复消息已经发送成功。
  • (3)发送方执行本地的事件逻辑(从A银行账户扣除一万元)。
  • (4)发送方根据本地事件执行结果向Broker发送二次确认(Commit或者Rollback)消息。如果Broker收到commit 则将第一阶段消息标记位可投递,订阅发就可以收到这个消息。如果Broker收到Rollback状态,则删除第一阶段的消息,订阅方就收不到消息。
  • (5)如果步骤 4)出现异常,commit/rollback 消息不能到达broker,服务器在进过固定时间段后将对“待确认”的消息发起回查请求
  • (6)发送端收到5)的消息请求后,检查对应消息的本地事件执行结果返回commit/rollback。
  • (7)事务消息的缺点:RocketMQ 依赖将数据顺序写入磁盘来提高性能,但是步骤4)却需要更改第一阶段消息的状态,这样会降低系统性能。
  • (8)三个类支持事务消息:LocalTransactionExecuter, TransactionMQProducer, TransactionCheckListener。

3.3 存储队里位置信息

  • (1)offset 含义:指某个Topic下的一条消息在某个Message Queue里的位置。
  • (2)Offset 分为本地文件类型Broker代存类型。当消息模式为CLUSTERING, Broker段控制和存储Offset的值,使用RemoteBrokerOffsetStore。当消息模式是BROADCASTING时,RocketMQ使用LocalFileOffsetStore, 把offset存放在本地。
  • (3)offset采用json格式存储。

第四章

4.1 NameServer 的功能

  • NameServer是整个消息队列的状态服务器,集群的各个组件 通过它来了解全局的信息。
  • NameServer 中的Broker, Topic 等状态信息不会被持久化存储,存储在内存中。

4.1.1 集群状态的存储

  • 在RouteInfoManager类中,通过map去存储。

4.1.2 状态维护逻辑

  • NameServer 根据Broker上报消息里的请求码做相应的处理,更新存储Map的信息。

4.2.2 为什么不用ZooKeeper

ZooKeeper功能强大,包括自动Master选举等。RocketMQ的架构不需要ZooKeeper复杂的功能,只要一个轻量级的元数据服务器即可。而且中间节RockMQ对稳定性要求高,NameServer代码少,好维护,少依赖一个另外的中间件,减少维护成本。

猜你喜欢

转载自blog.csdn.net/ZHANGYONGHAO604/article/details/83012017