RocketMQ技术调研

RocketMQ面试题 你们为什么使用mq?具体的使用场景是什么? mq的作用很简单,削峰填谷。以电商交易下单的场景来说,正向交易的过程可能涉及到创建订单、扣减库存、扣减活动预算、扣减积分等等。每个接口的耗时如果是100ms,那么理论上整个下单的链路就需要耗费400ms,这个时间显然是太长了。 如果这些操作全部同步处理的话,首先调用链路太长影响接口性能,其次分布式事务的问题很难处理,这时候像扣减预算和积分这种对实时一致性要求没有那么高的请求,完全就可以通过mq异步的方式去处理了。同时,考虑到异步带来的不一致的问题,我们可以 阅读详情

RocketMQ集群部署和架构

RocketMQ集群部署

版本: rocketmq-all-4.5.2-bin-release

Master-a:

10.*.*.11  hostname:11

Slave-a:

10.*.*.12 hostname:12

Master-b:

10.*.*.237 hostname:237

Slave-b:

10.*.*.241 hostname:241

Name Server :

10.*.14.11   10.*.14.12    10.*.14.241

说明:以上 Broker 与 Slave 配对是通过指定相同的brokerName 参数来配对,Master 的 BrokerId 必须是 0,Slave的BrokerId 必须是大与 0 的数。另外一个 Master 下面可以挂载多个 Slave,同一 Master 下的多个 Slave 通过指定不同的 BrokerId 来区分。

集群监控服务

rocketmq-console-ng-1.0.1.jar

启动服务命令:nohup java –jar rocketmq-console-ng-1.0.1.jar> /data/rocketmq-console-log/rocketmq-console.log  2>&1 &

地址:http://10.*.14.241:14300/#/cluster

 

集群服务可用状态检查

通过 mqadmin 运维命令查看集群状态

bin/mqadmin clusterList -n 10.*.14.241:9876

说明:其中 BID 为 0 的表示 Master,其余都是 Follower

过程中遇到的问题

主要原因是linux下缺少依赖包。$JAVA_HOME/jre/lib/ext/,找到sunjce_provider.jar 然后拷贝至linux下对应的目录即可。 或者配置环境变量能加载到这个jar。

其他网络端口权限问题:

 

涉及服务端口:

10.*.14.11:9876;10.*.14.12:9876;10.*.14.241:9876

10.*.14.241:14300

RocketMQ技术基本概念

Topic:对于RocketMQ而言,Topic只是一个逻辑上的概念,真正的消息存储其实是在Topic中的Queue中。这样设计从开始就是为了解决大规模高并发下消息的顺序消费问题。和kafka中的topic类似

Tag :给消息打标签,用于区分一类消息,可为null,只有发送消息设置了tags,消费方在订阅消息时,才可以利用 tags 在 broker 做消息过滤。反之订阅了不存在的tags 也消费不到任何数据,也不会报异常。可以达到再次过滤目的。比如消费端可以只消费topic001中TagA的消息.

Queue:消息队列缓存数据,一个topic下有1或多个,可以类比kafka中的partition

Group:生产或消费的客户端标识,生产和消费都有,与kafka不同

msgID:消息ID ,msgId是mq自动生成的,可在控制台message中查找数据。如:msgId=0A06CD634F612437C6DC3ABF77950001

msgKey:消息唯一key,可以在控制台根据key查询消息或用于去重,需要在发送时设定,也可为null。 每个消息在业务层面的唯一标识码,要设置到 keys 字段,方便将来定位消息丢失问题回溯。由于是哈希索引,请务必保证 key 尽可能唯一,这样可以避免潜在的哈希冲突。

queueOffset(队列消息偏移量)、InstanceName(生产客户端实例名)

rocketmq-broker:接受生产者发来的消息并存储(通过调用rocketmq-store),消费者从这里取得消息。

rocketmq-client:提供发送、接受消息的客户端API。

rocketmq-namesrv:NameServer,类似于Zookeeper,这里保存着消息的TopicName,队列等运行时的元信息。(有点NameNode的味道)

rocketmq-store:消息、索引存储等

 

RocketMQ 非集群模式测试

测试环境:10.*.100.33:10911

 

  1. 多队列生产:且指定生产topic 的指定队列顺序

 

msg1发送响应:MsgId:0A06CD63432F2437C6DC31C3469D0000,发送状态:SEND_OK

msg1发送响应:MsgId:0A06CD63432F2437C6DC31C346BE0001,发送状态:SEND_OK

msg2发送响应:MsgId:0A06CD63432F2437C6DC31C346C60002,发送状态:SEND_OK

msg1发送响应:MsgId:0A06CD63432F2437C6DC31C346CD0003,发送状态:SEND_OK

msg3发送响应:MsgId:0A06CD63432F2437C6DC31C346D50004,发送状态:SEND_OK

msg1发送响应:MsgId:0A06CD63432F2437C6DC31C346DA0005,发送状态:SEND_OK

msg1发送响应:MsgId:0A06CD63432F2437C6DC31C346E00006,发送状态:SEND_OK

msg2发送响应:MsgId:0A06CD63432F2437C6DC31C346E40007,发送状态:SEND_OK

msg1发送响应:MsgId:0A06CD63432F2437C6DC31C346E90008,发送状态:SEND_OK

msg1发送响应:MsgId:0A06CD63432F2437C6DC31C346ED0009,发送状态:SEND_OK

msg1发送响应:MsgId:0A06CD63432F2437C6DC31C346F1000A,发送状态:SEND_OK

msg2发送响应:MsgId:0A06CD63432F2437C6DC31C346F4000B,发送状态:SEND_OK

msg1发送响应:MsgId:0A06CD63432F2437C6DC31C346F8000C,发送状态:SEND_OK

msg1发送响应:MsgId:0A06CD63432F2437C6DC31C346FB000D,发送状态:SEND_OK

msg1发送响应:MsgId:0A06CD63432F2437C6DC31C34701000E,发送状态:SEND_OK

msg2发送响应:MsgId:0A06CD63432F2437C6DC31C34704000F,发送状态:SEND_OK

msg1发送响应:MsgId:0A06CD63432F2437C6DC31C347080010,发送状态:SEND_OK

msg1发送响应:MsgId:0A06CD63432F2437C6DC31C3470C0011,发送状态:SEND_OK

msg3发送响应:MsgId:0A06CD63432F2437C6DC31C3470F0012,发送状态:SEND_OK

msg1发送响应:MsgId:0A06CD63432F2437C6DC31C347130013,发送状态:SEND_OK

msg2发送响应:MsgId:0A06CD63432F2437C6DC31C347160014,发送状态:SEND_OK

msg1发送响应:MsgId:0A06CD63432F2437C6DC31C347190015,发送状态:SEND_OK

 

Process finished with exit code 0

 

  1. 消费端订阅指定tag,且有序消费

 

消费TagB的情况: msgId: 0A06CD63432F2437C6DC31C346C60002 QueueId: 2 topic#tags: t_luo01,TagB msgs大小: 199 msg:北京 Hello RocketMQ 3

消费TagB的情况: msgId: 0A06CD63432F2437C6DC31C346E40007 QueueId: 2 topic#tags: t_luo01,TagB msgs大小: 199 msg:北京 Hello RocketMQ 9

消费TagB的情况: msgId: 0A06CD63432F2437C6DC31C346F4000B QueueId: 2 topic#tags: t_luo01,TagB msgs大小: 201 msg:北京 Hello RocketMQ 15

消费TagB的情况: msgId: 0A06CD63432F2437C6DC31C34704000F QueueId: 2 topic#tags: t_luo01,TagB msgs大小: 201 msg:北京 Hello RocketMQ 21

消费TagB的情况: msgId: 0A06CD63432F2437C6DC31C347160014 QueueId: 2 topic#tags: t_luo01,TagB msgs大小: 201 msg:北京 Hello RocketMQ 27

测试结论:

其中以TagB为例:生产中:30条数据 其中TagB 5条

topic:t_luo01

消费的数据量和顺序完全一致。

 

  1. 生产单线程且有序:1000条数据
  2. 单线程多队列顺序生产10000条:生产耗时 22s

 

生产1000条数据 多队列有序

 

  1. 多个消费客户端是否支持消息顺序执行
    日志添加  "消费者1"  "消费者2" 用来区分 不同的消费者
    启动C1,C2查看控制台消费者状况
    消费者1日志如下:

 

消费者2日志如下:

 

测试结论:

可以看到负载均衡,并且消息是有顺序的。同一个类型的消息都会放到同一个队列中。

 

发送状态:SEND_OKtag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 0

发送状态:SEND_OKtag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 1

发送状态:SEND_OKtag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 2

发送状态:SEND_OKtag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 3

发送状态:SEND_OKtag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 4

发送状态:SEND_OKtag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 5

发送状态:SEND_OKtag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 6

发送状态:SEND_OKtag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 7

发送状态:SEND_OKtag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 8

发送状态:SEND_OKtag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 9

发送状态:SEND_OKtag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 10

发送状态:SEND_OKtag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 11

发送状态:SEND_OKtag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 12

发送状态:SEND_OKtag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 13

发送状态:SEND_OKtag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 14

发送状态:SEND_OKtag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 15

发送状态:SEND_OKtag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 16

发送状态:SEND_OKtag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 17

发送状态:SEND_OKtag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 18

发送状态:SEND_OKtag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 19

发送状态:SEND_OKtag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 20

发送状态:SEND_OKtag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 21

发送状态:SEND_OKtag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 22

发送状态:SEND_OKtag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 23

发送状态:SEND_OKtag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 24

发送状态:SEND_OKtag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 25

发送状态:SEND_OKtag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 26

发送状态:SEND_OKtag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 27

发送状态:SEND_OKtag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 28

发送状态:SEND_OKtag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 29

生产数据总耗时: 548

 

消费者1 ==> 当前线程:ConsumeMessageThread_10 ,quenuID: 1 ,content: 北京 Hello RocketMQ 0

生产数据总耗时: 592080

消费者1 ==> 当前线程:ConsumeMessageThread_11 ,quenuID: 2 ,content: 北京 Hello RocketMQ 10

生产数据总耗时: 592080

消费者1 ==> 当前线程:ConsumeMessageThread_10 ,quenuID: 1 ,content: 北京 Hello RocketMQ 1

生产数据总耗时: 592080

消费者1 ==> 当前线程:ConsumeMessageThread_11 ,quenuID: 2 ,content: 北京 Hello RocketMQ 11

生产数据总耗时: 592081

消费者1 ==> 当前线程:ConsumeMessageThread_12 ,quenuID: 3 ,content: 北京 Hello RocketMQ 20

生产数据总耗时: 592081

消费者1 ==> 当前线程:ConsumeMessageThread_10 ,quenuID: 1 ,content: 北京 Hello RocketMQ 2

生产数据总耗时: 592081

消费者1 ==> 当前线程:ConsumeMessageThread_12 ,quenuID: 3 ,content: 北京 Hello RocketMQ 21

生产数据总耗时: 592081

消费者1 ==> 当前线程:ConsumeMessageThread_10 ,quenuID: 1 ,content: 北京 Hello RocketMQ 3

生产数据总耗时: 592081

消费者1 ==> 当前线程:ConsumeMessageThread_10 ,quenuID: 1 ,content: 北京 Hello RocketMQ 4

生产数据总耗时: 592081

消费者1 ==> 当前线程:ConsumeMessageThread_13 ,quenuID: 1 ,content: 北京 Hello RocketMQ 5

生产数据总耗时: 592084

消费者1 ==> 当前线程:ConsumeMessageThread_13 ,quenuID: 1 ,content: 北京 Hello RocketMQ 6

生产数据总耗时: 592084

消费者1 ==> 当前线程:ConsumeMessageThread_13 ,quenuID: 1 ,content: 北京 Hello RocketMQ 7

生产数据总耗时: 592084

消费者1 ==> 当前线程:ConsumeMessageThread_13 ,quenuID: 1 ,content: 北京 Hello RocketMQ 8

生产数据总耗时: 592084

消费者1 ==> 当前线程:ConsumeMessageThread_13 ,quenuID: 1 ,content: 北京 Hello RocketMQ 9

生产数据总耗时: 592084

消费者1 ==> 当前线程:ConsumeMessageThread_14 ,quenuID: 2 ,content: 北京 Hello RocketMQ 12

生产数据总耗时: 592084

消费者1 ==> 当前线程:ConsumeMessageThread_14 ,quenuID: 2 ,content: 北京 Hello RocketMQ 13

生产数据总耗时: 592084

消费者1 ==> 当前线程:ConsumeMessageThread_14 ,quenuID: 2 ,content: 北京 Hello RocketMQ 14

生产数据总耗时: 592085

消费者1 ==> 当前线程:ConsumeMessageThread_14 ,quenuID: 2 ,content: 北京 Hello RocketMQ 15

生产数据总耗时: 592085

消费者1 ==> 当前线程:ConsumeMessageThread_14 ,quenuID: 2 ,content: 北京 Hello RocketMQ 16

生产数据总耗时: 592085

消费者1 ==> 当前线程:ConsumeMessageThread_14 ,quenuID: 2 ,content: 北京 Hello RocketMQ 17

生产数据总耗时: 592085

消费者1 ==> 当前线程:ConsumeMessageThread_14 ,quenuID: 2 ,content: 北京 Hello RocketMQ 18

生产数据总耗时: 592085

消费者1 ==> 当前线程:ConsumeMessageThread_14 ,quenuID: 2 ,content: 北京 Hello RocketMQ 19

生产数据总耗时: 592085

消费者1 ==> 当前线程:ConsumeMessageThread_15 ,quenuID: 3 ,content: 北京 Hello RocketMQ 22

生产数据总耗时: 592369

消费者1 ==> 当前线程:ConsumeMessageThread_15 ,quenuID: 3 ,content: 北京 Hello RocketMQ 23

生产数据总耗时: 592370

消费者1 ==> 当前线程:ConsumeMessageThread_15 ,quenuID: 3 ,content: 北京 Hello RocketMQ 24

生产数据总耗时: 592370

消费者1 ==> 当前线程:ConsumeMessageThread_15 ,quenuID: 3 ,content: 北京 Hello RocketMQ 25

生产数据总耗时: 592370

消费者1 ==> 当前线程:ConsumeMessageThread_16 ,quenuID: 3 ,content: 北京 Hello RocketMQ 26

生产数据总耗时: 592373

消费者1 ==> 当前线程:ConsumeMessageThread_16 ,quenuID: 3 ,content: 北京 Hello RocketMQ 27

生产数据总耗时: 592373

消费者1 ==> 当前线程:ConsumeMessageThread_16 ,quenuID: 3 ,content: 北京 Hello RocketMQ 28

生产数据总耗时: 592373

消费者1 ==> 当前线程:ConsumeMessageThread_16 ,quenuID: 3 ,content: 北京 Hello RocketMQ 29

生产数据总耗时: 592373

 

测试结论:

可以看到生产端每个队列数据是有序的,从全局上来看,消息的消费不是有序的,但是每一个队列的消息是顺序消费的,且即便是多线程情况下(其实broker并不能完全保证消息的顺序消费,它仅仅能保证的消息的顺序发送)

所以需要保证消息的顺序消费,那么首先需要做到一组需要有序消费的消息发往同一个broker的同一个队列上,其次消费者端采用有序Listener(MessageListenerOrderly监听器)即可。

 

  1. 一个消费端订阅一个topic的多个tag消费,且有序:
    生产端代码和测试:

 

RocketMQLog:WARN Please initialize the logger system properly.

发送状态:SEND_OK,tag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 0

发送状态:SEND_OK,tag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 1

发送状态:SEND_OK,tag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 2

发送状态:SEND_OK,tag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 3

发送状态:SEND_OK,tag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 4

发送状态:SEND_OK,tag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 5

发送状态:SEND_OK,tag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 6

发送状态:SEND_OK,tag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 7

发送状态:SEND_OK,tag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 8

发送状态:SEND_OK,tag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 9

发送状态:SEND_OK,tag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 10

发送状态:SEND_OK,tag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 11

发送状态:SEND_OK,tag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 12

发送状态:SEND_OK,tag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 13

发送状态:SEND_OK,tag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 14

发送状态:SEND_OK,tag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 15

发送状态:SEND_OK,tag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 16

发送状态:SEND_OK,tag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 17

发送状态:SEND_OK,tag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 18

发送状态:SEND_OK,tag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 19

发送状态:SEND_OK,tag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 20

发送状态:SEND_OK,tag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 21

发送状态:SEND_OK,tag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 22

发送状态:SEND_OK,tag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 23

发送状态:SEND_OK,tag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 24

发送状态:SEND_OK,tag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 25

发送状态:SEND_OK,tag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 26

发送状态:SEND_OK,tag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 27

发送状态:SEND_OK,tag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 28

发送状态:SEND_OK,tag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 29

生产数据总耗时: 578

 

Process finished with exit code 0

 

消费端代码和测试情况:

 

Consumer Started.

消费者2 ==> 当前线程:ConsumeMessageThread_1 ,quenuID: 1 ,content: 北京 Hello RocketMQ 0

生产数据总耗时: 24095

消费者2 ==> 当前线程:ConsumeMessageThread_1 ,quenuID: 1 ,content: 北京 Hello RocketMQ 1

生产数据总耗时: 24096

消费者2 ==> 当前线程:ConsumeMessageThread_1 ,quenuID: 1 ,content: 北京 Hello RocketMQ 2

生产数据总耗时: 24097

消费者2 ==> 当前线程:ConsumeMessageThread_1 ,quenuID: 1 ,content: 北京 Hello RocketMQ 3

生产数据总耗时: 24097

消费者2 ==> 当前线程:ConsumeMessageThread_1 ,quenuID: 1 ,content: 北京 Hello RocketMQ 4

生产数据总耗时: 24097

消费者2 ==> 当前线程:ConsumeMessageThread_1 ,quenuID: 1 ,content: 北京 Hello RocketMQ 5

生产数据总耗时: 24097

消费者2 ==> 当前线程:ConsumeMessageThread_1 ,quenuID: 1 ,content: 北京 Hello RocketMQ 6

生产数据总耗时: 24097

消费者2 ==> 当前线程:ConsumeMessageThread_1 ,quenuID: 1 ,content: 北京 Hello RocketMQ 7

生产数据总耗时: 24097

消费者2 ==> 当前线程:ConsumeMessageThread_1 ,quenuID: 1 ,content: 北京 Hello RocketMQ 8

生产数据总耗时: 24097

消费者2 ==> 当前线程:ConsumeMessageThread_1 ,quenuID: 1 ,content: 北京 Hello RocketMQ 9

生产数据总耗时: 24097

消费者2 ==> 当前线程:ConsumeMessageThread_2 ,quenuID: 3 ,content: 北京 Hello RocketMQ 20

生产数据总耗时: 44106

消费者2 ==> 当前线程:ConsumeMessageThread_2 ,quenuID: 3 ,content: 北京 Hello RocketMQ 21

生产数据总耗时: 44106

消费者2 ==> 当前线程:ConsumeMessageThread_2 ,quenuID: 3 ,content: 北京 Hello RocketMQ 22

生产数据总耗时: 44106

消费者2 ==> 当前线程:ConsumeMessageThread_2 ,quenuID: 3 ,content: 北京 Hello RocketMQ 23

生产数据总耗时: 44107

消费者2 ==> 当前线程:ConsumeMessageThread_2 ,quenuID: 3 ,content: 北京 Hello RocketMQ 24

生产数据总耗时: 44107

消费者2 ==> 当前线程:ConsumeMessageThread_2 ,quenuID: 3 ,content: 北京 Hello RocketMQ 25

生产数据总耗时: 44107

消费者2 ==> 当前线程:ConsumeMessageThread_2 ,quenuID: 3 ,content: 北京 Hello RocketMQ 26

生产数据总耗时: 44107

消费者2 ==> 当前线程:ConsumeMessageThread_2 ,quenuID: 3 ,content: 北京 Hello RocketMQ 27

生产数据总耗时: 44107

消费者2 ==> 当前线程:ConsumeMessageThread_2 ,quenuID: 3 ,content: 北京 Hello RocketMQ 28

生产数据总耗时: 44107

消费者2 ==> 当前线程:ConsumeMessageThread_2 ,quenuID: 3 ,content: 北京 Hello RocketMQ 29

生产数据总耗时: 44107

 

  1. 同一个topic下tag的问题:
    同一个消费组中,设置不同tag时,后启动的消费者会覆盖先启动的消费者设置的tag,会导致客户端发现数据有丢失情况。
    所以每个客户端尽量都使用不同的唯一groupID,规避这种问题的出现。这个设计原理和kafka counsumer 同一个group同一时刻消费同一个topic的类似。

 

具体测试情况如下:

 

先启动的consumer1客户端: 没有消费到任何数据

 

后启动的consumer2客户端: 消费到了一部分数据

 

  1. Rocketmq实现顺序消费机制:
    1.rocketmq保证同一个订单的消息,一定要发送到同一个队列
  2. 并且该队列只有一个消费者,也就是说 同一个队列,不能出现多个消费者并行消费的情况。但一个队列只有一个消费者,性能如何?关于这个情况Rocketmq的解决方法是同一个队列不能并行消费,但是可以并行消费不同的队列。比如:同时多笔订单之间是可以并行消费的。
  3. RocketMQ中同一个Topic 不同的group订阅消费不同的tag场景:且保证有序
    生产端:
    topic name: t_luo01
    group:p_luo01
    tags: TagA、TagB、TagC
    数据量:分别10条 总共30条

 

消费端 多线程消费服务1:

topic name: t_luo01

group: c_luo02

tags: TTagB

消费的数据量:10条 且有序

 

Consumer Started.

消费者1 ==> 当前线程:ConsumeMessageThread_1 ,quenuID: 2 ,content: 北京 Hello RocketMQ 10

生产数据总耗时: 4121

消费者1 ==> 当前线程:ConsumeMessageThread_1 ,quenuID: 2 ,content: 北京 Hello RocketMQ 11

生产数据总耗时: 4122

消费者1 ==> 当前线程:ConsumeMessageThread_1 ,quenuID: 2 ,content: 北京 Hello RocketMQ 12

生产数据总耗时: 4123

消费者1 ==> 当前线程:ConsumeMessageThread_1 ,quenuID: 2 ,content: 北京 Hello RocketMQ 13

生产数据总耗时: 4123

消费者1 ==> 当前线程:ConsumeMessageThread_1 ,quenuID: 2 ,content: 北京 Hello RocketMQ 14

生产数据总耗时: 4123

消费者1 ==> 当前线程:ConsumeMessageThread_1 ,quenuID: 2 ,content: 北京 Hello RocketMQ 15

生产数据总耗时: 4123

消费者1 ==> 当前线程:ConsumeMessageThread_1 ,quenuID: 2 ,content: 北京 Hello RocketMQ 16

生产数据总耗时: 4123

消费者1 ==> 当前线程:ConsumeMessageThread_1 ,quenuID: 2 ,content: 北京 Hello RocketMQ 17

生产数据总耗时: 4123

消费者1 ==> 当前线程:ConsumeMessageThread_1 ,quenuID: 2 ,content: 北京 Hello RocketMQ 18

生产数据总耗时: 4124

消费者1 ==> 当前线程:ConsumeMessageThread_1 ,quenuID: 2 ,content: 北京 Hello RocketMQ 19

生产数据总耗时: 4124

 

消费端 多线程消费服务2:

topic name: t_luo01

group:c_luo03

tags: TagA、TagC

消费的数据量:20条 且分别有序

 

消费者2 ==> 当前线程:ConsumeMessageThread_3 ,quenuID: 1 ,content: 北京 Hello RocketMQ 0

生产数据总耗时: 25239

消费者2 ==> 当前线程:ConsumeMessageThread_3 ,quenuID: 1 ,content: 北京 Hello RocketMQ 1

生产数据总耗时: 25239

消费者2 ==> 当前线程:ConsumeMessageThread_3 ,quenuID: 1 ,content: 北京 Hello RocketMQ 2

生产数据总耗时: 25239

消费者2 ==> 当前线程:ConsumeMessageThread_3 ,quenuID: 1 ,content: 北京 Hello RocketMQ 3

生产数据总耗时: 25239

消费者2 ==> 当前线程:ConsumeMessageThread_3 ,quenuID: 1 ,content: 北京 Hello RocketMQ 4

生产数据总耗时: 25239

消费者2 ==> 当前线程:ConsumeMessageThread_4 ,quenuID: 1 ,content: 北京 Hello RocketMQ 5

生产数据总耗时: 25242

消费者2 ==> 当前线程:ConsumeMessageThread_4 ,quenuID: 1 ,content: 北京 Hello RocketMQ 6

生产数据总耗时: 25242

消费者2 ==> 当前线程:ConsumeMessageThread_4 ,quenuID: 1 ,content: 北京 Hello RocketMQ 7

生产数据总耗时: 25242

消费者2 ==> 当前线程:ConsumeMessageThread_4 ,quenuID: 1 ,content: 北京 Hello RocketMQ 8

生产数据总耗时: 25242

消费者2 ==> 当前线程:ConsumeMessageThread_4 ,quenuID: 1 ,content: 北京 Hello RocketMQ 9

生产数据总耗时: 25243

消费者2 ==> 当前线程:ConsumeMessageThread_5 ,quenuID: 3 ,content: 北京 Hello RocketMQ 20

生产数据总耗时: 25496

消费者2 ==> 当前线程:ConsumeMessageThread_5 ,quenuID: 3 ,content: 北京 Hello RocketMQ 21

生产数据总耗时: 25496

消费者2 ==> 当前线程:ConsumeMessageThread_5 ,quenuID: 3 ,content: 北京 Hello RocketMQ 22

生产数据总耗时: 25496

消费者2 ==> 当前线程:ConsumeMessageThread_5 ,quenuID: 3 ,content: 北京 Hello RocketMQ 23

生产数据总耗时: 25496

消费者2 ==> 当前线程:ConsumeMessageThread_5 ,quenuID: 3 ,content: 北京 Hello RocketMQ 24

生产数据总耗时: 25496

消费者2 ==> 当前线程:ConsumeMessageThread_5 ,quenuID: 3 ,content: 北京 Hello RocketMQ 25

生产数据总耗时: 25497

消费者2 ==> 当前线程:ConsumeMessageThread_6 ,quenuID: 3 ,content: 北京 Hello RocketMQ 26

生产数据总耗时: 25501

消费者2 ==> 当前线程:ConsumeMessageThread_6 ,quenuID: 3 ,content: 北京 Hello RocketMQ 27

生产数据总耗时: 25502

消费者2 ==> 当前线程:ConsumeMessageThread_6 ,quenuID: 3 ,content: 北京 Hello RocketMQ 28

生产数据总耗时: 25502

消费者2 ==> 当前线程:ConsumeMessageThread_6 ,quenuID: 3 ,content: 北京 Hello RocketMQ 29

生产数据总耗时: 25502

 

  1. RocketMQ中同一个Topic  同一个的group订阅消费不同的tag场景:且保证有序
    生产端:
    topic name: t_luo01
    tags: TagA、TagB、TagC
    数据量:分别10条 总共30条

 

测试结论: 不同的消费端用同一个group 订阅不同的tag,后启动的消费端服务会覆盖前一个的的tag,会导致前一个消费客户端消费不到数据。所有建议消费端都尽量采用不同的group 规避这种问题的发生。

 

  1. RocketMQ提供了3种模式的Producer:
    NormalProducer(普通)、OrderProducer(顺序)、TransactionProducer(事务)
    NormalProducer模式调用传统的send方法,消息是无序的。
    OrderProducer 模式调用Send方法中有一个MessageQueueSelector,将用于指定特定的消息发往特定的队列中。
    TransactionProducer模式对数据状态要求严格一致性的场景,但性能有降低。
  2. Producer客户端发送消息的三种状态方式:
  3. 可靠同步发送
    同步发送是指消息发送方发出数据后,会在收到接收方发回响应之后才发下一个数据包的通讯方式。

 

相关代码测试:

说明:sendStatus=SLAVE_NOT_AVAILABLE

目前集群部署模式是 2s-2m-sync 双主双从+同步 如果代理的角色是SYNC_MASTER(默认是ASYNC_MASTER),但是没有配置 Slave Broker ,将获得这个状态。

其他返回状态说明:SEND_OK

SEND_OK 并不意味着它是可靠的。为了确保没有信息会丢失,应启用 SYNC_MASTER 或 SYNC_FLUSH。但性能降低10%左右。

 

其中:

SendResult [sendStatus=SLAVE_NOT_AVAILABLE, msgId=0A06CD634D2B2437C6DC372832620000, offsetMsgId=0A030E0B00002A9F00000000000626BC, messageQueue=MessageQueue [topic=PushTopic, brokerName=broker-a, queueId=1], queueOffset=51]

已发送到master节点 但slave配置是异步同步模式

 

同步发送中 还有同步有序发送消息到指定队列中:

主要依赖MessageQueueSelector方法实现,RocketMQ默认提供了两种MessageQueueSelector实现:随机/Hash 根据实际业务情况可灵活选择设计

具体代码实现和测试如下:

 

  1. 可靠异步发送
    异步发送是指发送方发出数据后,不等接收方发回响应,接着发送下个数据包的通讯方式。 MQ 的异步发送,需要用户实现异步发送回调接口(SendCallback)。消息发送方在发送了一条消息后,不需要等待服务器响应即可返回,进行第二条消息发送。发送方通过回调接口接收服务器响应,并对响应结果进行处理。

 

相关代码测试:

由于本地开发连接虚拟机中的 nameServer 时要经过 Linux 系统的防火墙,而防火墙会有超时的机制,在网络连接长时间不传输数据时,会关闭这个 TCP

的会话,关闭后再读写,就会导致这个异常问题。

 

  1. 单向(Oneway)发送
    单向(Oneway)发送特点为发送方只负责发送消息,不等待服务器回应且没有回调函数触发,即只发送请求不等待应答。 此方式发送消息的过程耗时非常短,一般在微秒级别。

 

相关代码测试:

说明:生产端无返回状态,消费端多线程可正常消费数据

 

测试结论三种方式比较:

 

如果希望在一个Producer JVM客户端中有多个生产者进行大规模数据处理,建议:

1.可以多个生产者一起使用异步发送

2.为每个生产者单独设置setInstanceName 做区分

代码如:producer.setInstanceName("TxProducer-instance1");

 

  1. RocketMQ消费端模式:
    目前支持两种消费监听器模式MessageListenerConcurrently和MessageListenerOrderly。
    其中MessageListenerOrderly 保证顺序消费,消费端接收的是同一个队列的消息,避免多线程时顺序错乱
    代码实现和测试:
    MessageListenerConcurrently 监听模式用来高并发无序消费数
    代码实现和测试:
  2. RocketMQ 事务型生产消费模式:
    RocketMQ从4.3.0版本开始,支持了事务消息。
    一般分布式采用2pc(2 phase commit)模式(两阶段提交协议:预留和确认),安全性高,但是因为长连接导致长时间等待。(当然也有三阶段提交)
    而RocketMQ采用两阶段补偿型,TCC(Try-Confirm-Cancel)的简称。采用2PC的方案来提交事务消息,同时增加一个补偿逻辑来处理二阶段超时或者失败的消息。

 

上图说明了事务消息的大致方案,分为两个逻辑:正常事务消息的发送及提交、事务消息的补偿流程

事务消息发送及提交:

 

  1. 发送消息(half消息)
  2. 服务端响应消息写入结果
  3. 根据发送结果执行本地事务(如果写入失败,此时half消息对业务不可见,本地逻辑不执行)
  4. 根据本地事务状态执行Commit或者Rollback(Commit操作生成消息索引,消息对消费者可见)
    Ack消息的3种状态
    Broker是根据Producer发送过来的状态码,来决定下一步的操作TransactionStatus.CommitTransaction、TransactionStatus.RollbackTransaction、TransactionStatus.Unknown(提交、回滚、重试)
  5. 事务型生产消费代码实现和测试:

 

生产者代码修改,需添加:

sendMessage变化:TransactionSendResult

producer变化:   TransactionMQProducer

添加监听:        TransactionListener

 

遇到问题:

transactionProducer 生产后无法消费

maven中缺少 rocketmq-all依赖导致

解决:引入下面的依赖

 

org.apache.rocketmq

rocketmq-all

4.5.2

 

生产事务数据代码和测试:

 

msg :hello 0

arg :tq

main ---> SendResult [sendStatus=SEND_OK, msgId=0A06CD6353172437C6DC3CCF29760000, offsetMsgId=null, messageQueue=MessageQueue [topic=TopicTransaction, brokerName=broker-a, queueId=0], queueOffset=239]

msg :hello 1

arg :tq

这里处理业务逻辑,如操作数据库,失败情况下进行ROLLBACK

main ---> SendResult [sendStatus=SEND_OK, msgId=0A06CD6353172437C6DC3CCF299F0001, offsetMsgId=null, messageQueue=MessageQueue [topic=TopicTransaction, brokerName=broker-a, queueId=1], queueOffset=240]

msg :hello 2

arg :tq

main ---> SendResult [sendStatus=SEND_OK, msgId=0A06CD6353172437C6DC3CCF29B10002, offsetMsgId=null, messageQueue=MessageQueue [topic=TopicTransaction, brokerName=broker-a, queueId=2], queueOffset=241]

 

Process finished with exit code 0

消费端代码和测试:和普通消费一样

 

transaction Consumer started...

ConsumeMessageThread_1,Receive: [MessageExt [queueId=0, storeSize=274, queueOffset=3, sysFlag=8, bornTimestamp=1576149809528, bornHost=/10.6.205.99:56034, storeTimestamp=1576149809565, storeHost=/10.2.100.33:10911, msgId=0A02642100002A9F000000000001573B, commitLogOffset=87867, bodyCRC=552077809, reconsumeTimes=0, preparedTransactionOffset=87585, toString()=Message{topic='TopicTransaction', flag=0, properties={MIN_OFFSET=0, REAL_TOPIC=TopicTransaction, MAX_OFFSET=4, KEYS=key, TRAN_MSG=true, CONSUME_START_TIME=1576149809578, UNIQ_KEY=0A06CD6353172437C6DC3CCF29760000, WAIT=true, PGROUP=transaction_producer, TAGS=transaction0, REAL_QID=0}, body=[104, 101, 108, 108, 111, 32, 48], transactionId='0A06CD6353172437C6DC3CCF29760000'}]]

收到消息: topic:TopicTransaction tags:transaction0 msg:hello 0

ConsumeMessageThread_2,Receive: [MessageExt [queueId=2, storeSize=274, queueOffset=6, sysFlag=8, bornTimestamp=1576149809585, bornHost=/10.6.205.99:56034, storeTimestamp=1576149809600, storeHost=/10.2.100.33:10911, msgId=0A02642100002A9F0000000000015B95, commitLogOffset=88981, bodyCRC=1323722973, reconsumeTimes=0, preparedTransactionOffset=88699, toString()=Message{topic='TopicTransaction', flag=0, properties={MIN_OFFSET=0, REAL_TOPIC=TopicTransaction, MAX_OFFSET=7, KEYS=key, TRAN_MSG=true, CONSUME_START_TIME=1576149809605, UNIQ_KEY=0A06CD6353172437C6DC3CCF29B10002, WAIT=true, PGROUP=transaction_producer, TAGS=transaction2, REAL_QID=2}, body=[104, 101, 108, 108, 111, 32, 50], transactionId='0A06CD6353172437C6DC3CCF29B10002'}]]

收到消息: topic:TopicTransaction tags:transaction2 msg:hello 2

 

本地事务代码:

 

非集群模式下,事务型生产消息代码和测试:

 

事务机制相关代码:

 

RocketMQLog:WARN Please initialize the logger system properly.

处理业务逻辑,如操作数据库,失败情况下进行事务ROLLBACK

Thu Dec 12 20:25:32 CST 2019消息: 事务 message bj RocketMQ 0,Tag: TagA, SendResult [sendStatus=SEND_OK, msgId=0A06CD6354502437C6DC3D07F9800000, offsetMsgId=null, messageQueue=MessageQueue [topic=tx_t002, brokerName=broker-a, queueId=3], queueOffset=302]

Thu Dec 12 20:25:32 CST 2019消息: 事务 message bj RocketMQ 1,Tag: TagB, SendResult [sendStatus=SEND_OK, msgId=0A06CD6354502437C6DC3D07F9B30001, offsetMsgId=null, messageQueue=MessageQueue [topic=tx_t002, brokerName=broker-a, queueId=0], queueOffset=303]

Thu Dec 12 20:25:32 CST 2019消息: 事务 message bj RocketMQ 2,Tag: TagC, SendResult [sendStatus=SEND_OK, msgId=0A06CD6354502437C6DC3D07F9BB0002, offsetMsgId=null, messageQueue=MessageQueue [topic=tx_t002, brokerName=broker-a, queueId=1], queueOffset=304]

Thu Dec 12 20:25:32 CST 2019消息: 事务 message bj RocketMQ 3,Tag: TagD, SendResult [sendStatus=SEND_OK, msgId=0A06CD6354502437C6DC3D07F9CB0003, offsetMsgId=null, messageQueue=MessageQueue [topic=tx_t002, brokerName=broker-a, queueId=2], queueOffset=305]

Thu Dec 12 20:25:32 CST 2019消息: 事务 message bj RocketMQ 4,Tag: TagE, SendResult [sendStatus=SEND_OK, msgId=0A06CD6354502437C6DC3D07F9F60004, offsetMsgId=null, messageQueue=MessageQueue [topic=tx_t002, brokerName=broker-a, queueId=3], queueOffset=306]

处理业务逻辑,如操作数据库,失败情况下进行事务ROLLBACK

Thu Dec 12 20:25:32 CST 2019消息: 事务 message bj RocketMQ 5,Tag: TagA, SendResult [sendStatus=SEND_OK, msgId=0A06CD6354502437C6DC3D07FA060005, offsetMsgId=null, messageQueue=MessageQueue [topic=tx_t002, brokerName=broker-a, queueId=0], queueOffset=307]

Thu Dec 12 20:25:32 CST 2019消息: 事务 message bj RocketMQ 6,Tag: TagB, SendResult [sendStatus=SEND_OK, msgId=0A06CD6354502437C6DC3D07FA180006, offsetMsgId=null, messageQueue=MessageQueue [topic=tx_t002, brokerName=broker-a, queueId=1], queueOffset=308]

Thu Dec 12 20:25:32 CST 2019消息: 事务 message bj RocketMQ 7,Tag: TagC, SendResult [sendStatus=SEND_OK, msgId=0A06CD6354502437C6DC3D07FA280007, offsetMsgId=null, messageQueue=MessageQueue [topic=tx_t002, brokerName=broker-a, queueId=2], queueOffset=309]

Thu Dec 12 20:25:33 CST 2019消息: 事务 message bj RocketMQ 8,Tag: TagD, SendResult [sendStatus=SEND_OK, msgId=0A06CD6354502437C6DC3D07FA380008, offsetMsgId=null, messageQueue=MessageQueue [topic=tx_t002, brokerName=broker-a, queueId=3], queueOffset=310]

Thu Dec 12 20:25:33 CST 2019消息: 事务 message bj RocketMQ 9,Tag: TagE, SendResult [sendStatus=SEND_OK, msgId=0A06CD6354502437C6DC3D07FA4A0009, offsetMsgId=null, messageQueue=MessageQueue [topic=tx_t002, brokerName=broker-a, queueId=0], queueOffset=311]

 

Process finished with exit code 0

 

非集群模式下,消费端代码和测试:

 

transaction Consumer Started...

Thu Dec 12 20:26:09 CST 2019 消费者 ==> 当前线程: ConsumeMessageThread_4,storeHost: /10.2.100.33:10911,Tag: TagB,quenuID: 0 ,content: 事务 message bj RocketMQ 1

Thu Dec 12 20:26:09 CST 2019 消费者 ==> 当前线程: ConsumeMessageThread_2,storeHost: /10.2.100.33:10911,Tag: TagD,quenuID: 2 ,content: 事务 message bj RocketMQ 3

Thu Dec 12 20:26:09 CST 2019 消费者 ==> 当前线程: ConsumeMessageThread_1,storeHost: /10.2.100.33:10911,Tag: TagC,quenuID: 1 ,content: 事务 message bj RocketMQ 2

Thu Dec 12 20:26:09 CST 2019 消费者 ==> 当前线程: ConsumeMessageThread_3,storeHost: /10.2.100.33:10911,Tag: TagE,quenuID: 3 ,content: 事务 message bj RocketMQ 4

Thu Dec 12 20:26:09 CST 2019 消费者 ==> 当前线程: ConsumeMessageThread_4,storeHost: /10.2.100.33:10911,Tag: TagE,quenuID: 0 ,content: 事务 message bj RocketMQ 9

Thu Dec 12 20:26:09 CST 2019 消费者 ==> 当前线程: ConsumeMessageThread_2,storeHost: /10.2.100.33:10911,Tag: TagC,quenuID: 2 ,content: 事务 message bj RocketMQ 7

Thu Dec 12 20:26:09 CST 2019 消费者 ==> 当前线程: ConsumeMessageThread_3,storeHost: /10.2.100.33:10911,Tag: TagD,quenuID: 3 ,content: 事务 message bj RocketMQ 8

Thu Dec 12 20:26:09 CST 2019 消费者 ==> 当前线程: ConsumeMessageThread_1,storeHost: /10.2.100.33:10911,Tag: TagB,quenuID: 1 ,content: 事务 message bj RocketMQ 6

 

Process finished with exit code 130

 

结果分析说明:

 

  1. RocetkMQ生产端本地事务未提交的事务数据,这些对消费端是不可见的。
    其中TagA的数据未提交,在消费端中的数据只消费到了TagA以外的其他所有数据。
  2. 发现事务型消息消费端 有30s的延迟消费情况。
  3. 消费端要能成功消费 必须 sendStatus=SEND_OK,否则消费不到数据。(集群模式会测试到)
  4. 事务型消息衍生出来要考虑的问题:
  5. 这在监控界面会看到生产和消费的数据数量不一致,那不一致是未提交事务的影响,还是消费延迟阻塞的影响。会对监控者 造成干扰,需要考虑区分。
  6. 事务中未提交的 ROLLBACK_MESSAGE 数据,如何回溯和补偿问题。需要业务端技术设计和代码实现。
  7. RocketMQ 3.2.6 版本前官方社区版本事务消息的补偿机制流程:
    (1)对没有Commit/Rollback的事务消息(pending状态的消息),从服务端发起一次“回查”
    (2)Producer收到回查消息,检查回查消息对应的本地事务的状态
    (3)根据本地事务状态,重新Commit或者Rollback
    补偿阶段用于解决消息Commit或者Rollback发生超时或者失败的情况。

 

因非商业RocketMQ 3.2.6版本后取消回查机制:

//事务回查最大数

producer.setCheckRequestHoldMax(200);

//事务最大并发数

producer.setCheckThreadPoolMaxSize(20);

//事务最小并发数

producer.setCheckThreadPoolMinSize(5);

producer.setExecutorService(executorService);

等都已经过期没有作用,本来是用于开启多线程进行回查用。

测试结论:3.2.6 版本后非社区的Rocketmq取消了事务回查机制,如果丢失需要自己手动通过key值回查补偿。(可先在代码中实现代码retry机制,然后在回溯补偿机制)

集群模式生产消费:

集群环境:

RocketMQ NAMESRV_ADDR=10.3.14.11:9876;10.3.14.12:9876;10.3.14.241:9876

 

  1. 非事务型有序生产数据代码和测试:

 

RocketMQLog:WARN Please initialize the logger system properly.

发送状态:SLAVE_NOT_AVAILABLE,tag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 0

发送状态:SLAVE_NOT_AVAILABLE,tag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 1

发送状态:SLAVE_NOT_AVAILABLE,tag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 2

发送状态:SLAVE_NOT_AVAILABLE,tag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 3

发送状态:SLAVE_NOT_AVAILABLE,tag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 4

发送状态:SLAVE_NOT_AVAILABLE,tag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 5

发送状态:SLAVE_NOT_AVAILABLE,tag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 6

发送状态:SLAVE_NOT_AVAILABLE,tag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 7

发送状态:SLAVE_NOT_AVAILABLE,tag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 8

发送状态:SLAVE_NOT_AVAILABLE,tag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 9

发送状态:SLAVE_NOT_AVAILABLE,tag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 10

发送状态:SLAVE_NOT_AVAILABLE,tag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 11

发送状态:SLAVE_NOT_AVAILABLE,tag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 12

发送状态:SLAVE_NOT_AVAILABLE,tag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 13

发送状态:SLAVE_NOT_AVAILABLE,tag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 14

发送状态:SLAVE_NOT_AVAILABLE,tag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 15

发送状态:SLAVE_NOT_AVAILABLE,tag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 16

发送状态:SLAVE_NOT_AVAILABLE,tag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 17

发送状态:SLAVE_NOT_AVAILABLE,tag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 18

发送状态:SLAVE_NOT_AVAILABLE,tag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 19

发送状态:SLAVE_NOT_AVAILABLE,tag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 20

发送状态:SLAVE_NOT_AVAILABLE,tag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 21

发送状态:SLAVE_NOT_AVAILABLE,tag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 22

发送状态:SLAVE_NOT_AVAILABLE,tag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 23

发送状态:SLAVE_NOT_AVAILABLE,tag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 24

发送状态:SLAVE_NOT_AVAILABLE,tag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 25

发送状态:SLAVE_NOT_AVAILABLE,tag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 26

发送状态:SLAVE_NOT_AVAILABLE,tag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 27

发送状态:SLAVE_NOT_AVAILABLE,tag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 28

发送状态:SLAVE_NOT_AVAILABLE,tag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 29

 

Process finished with exit code 0

 

多线程指定Tag顺序消费:

consumer.subscribe("t_luo01", "TagA||TagC");

 

测试结果问题:

 

  1. 发现集群模式,消费数据时 只从storeHost: /10.3.14.11:10911 所在master节点push数据。(数据均衡问题?)
  2. 监控界面分析:

 

集群模式生产消费 发现数据的生产和消费也都在一个master-a 上。

监控工具问题: master-a  stop后,在start 发现broker-a 上的监控数据都归零。 继续生产消费发现如下异常问题:生产数据>消费数量

 

  1. 集群模式下生产消费 同一个topic生产过程中,增加Tag 消费情况:
  2. 集群模式生产消费HA:
    master节点生产消费HA:非事务生产数据

 

RocketMQLog:WARN Please initialize the logger system properly.

发送状态:SLAVE_NOT_AVAILABLE,tag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 0

发送状态:SLAVE_NOT_AVAILABLE,tag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 1

发送状态:SLAVE_NOT_AVAILABLE,tag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 2

发送状态:SLAVE_NOT_AVAILABLE,tag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 3

发送状态:SLAVE_NOT_AVAILABLE,tag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 4

发送状态:SLAVE_NOT_AVAILABLE,tag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 5

发送状态:SLAVE_NOT_AVAILABLE,tag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 6

发送状态:SLAVE_NOT_AVAILABLE,tag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 7

发送状态:SLAVE_NOT_AVAILABLE,tag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 8

发送状态:SLAVE_NOT_AVAILABLE,tag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 9

发送状态:SLAVE_NOT_AVAILABLE,tag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 10

发送状态:SLAVE_NOT_AVAILABLE,tag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 11

发送状态:SLAVE_NOT_AVAILABLE,tag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 12

发送状态:SLAVE_NOT_AVAILABLE,tag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 13

发送状态:SLAVE_NOT_AVAILABLE,tag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 14

发送状态:SLAVE_NOT_AVAILABLE,tag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 15

发送状态:SLAVE_NOT_AVAILABLE,tag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 16

发送状态:SLAVE_NOT_AVAILABLE,tag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 17

发送状态:SLAVE_NOT_AVAILABLE,tag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 18

发送状态:SLAVE_NOT_AVAILABLE,tag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 19

发送状态:SLAVE_NOT_AVAILABLE,tag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 20

发送状态:SLAVE_NOT_AVAILABLE,tag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 21

发送状态:SLAVE_NOT_AVAILABLE,tag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 22

发送状态:SLAVE_NOT_AVAILABLE,tag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 23

发送状态:SLAVE_NOT_AVAILABLE,tag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 24

发送状态:SLAVE_NOT_AVAILABLE,tag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 25

发送状态:SLAVE_NOT_AVAILABLE,tag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 26

发送状态:SLAVE_NOT_AVAILABLE,tag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 27

发送状态:SLAVE_NOT_AVAILABLE,tag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 28

发送状态:SLAVE_NOT_AVAILABLE,tag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 29

 

Process finished with exit code 0

 

预先集群模式下给topic:t_luo01 成功发送30条数据:

 

stop broker-a master 节点服务:

 

集群模式: 生产端对topic: t_luo01  发送数据,客户端报以下异常

 

启动消费端看是否能从slave节点消费到之前已经发送的数据

结果:没有从slave节点消费到这30条数据! 需要排查分析原因!!!

推断可能和 发送返回状态:SLAVE_NOT_AVAILABLE 状态有关。Slave节点没生效。

 

新建topic 对新topic 生产端 发送数据:

 

RocketMQLog:WARN Please initialize the logger system properly.

发送状态:SLAVE_NOT_AVAILABLE,tag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 0

发送状态:SLAVE_NOT_AVAILABLE,tag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 1

发送状态:SLAVE_NOT_AVAILABLE,tag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 2

发送状态:SLAVE_NOT_AVAILABLE,tag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 3

发送状态:SLAVE_NOT_AVAILABLE,tag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 4

发送状态:SLAVE_NOT_AVAILABLE,tag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 5

发送状态:SLAVE_NOT_AVAILABLE,tag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 6

发送状态:SLAVE_NOT_AVAILABLE,tag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 7

发送状态:SLAVE_NOT_AVAILABLE,tag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 8

发送状态:SLAVE_NOT_AVAILABLE,tag: TagA,队列ID: 1,消息体: 北京 Hello RocketMQ 9

发送状态:SLAVE_NOT_AVAILABLE,tag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 10

发送状态:SLAVE_NOT_AVAILABLE,tag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 11

发送状态:SLAVE_NOT_AVAILABLE,tag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 12

发送状态:SLAVE_NOT_AVAILABLE,tag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 13

发送状态:SLAVE_NOT_AVAILABLE,tag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 14

发送状态:SLAVE_NOT_AVAILABLE,tag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 15

发送状态:SLAVE_NOT_AVAILABLE,tag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 16

发送状态:SLAVE_NOT_AVAILABLE,tag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 17

发送状态:SLAVE_NOT_AVAILABLE,tag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 18

发送状态:SLAVE_NOT_AVAILABLE,tag: TagB,队列ID: 2,消息体: 北京 Hello RocketMQ 19

发送状态:SLAVE_NOT_AVAILABLE,tag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 20

发送状态:SLAVE_NOT_AVAILABLE,tag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 21

发送状态:SLAVE_NOT_AVAILABLE,tag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 22

发送状态:SLAVE_NOT_AVAILABLE,tag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 23

发送状态:SLAVE_NOT_AVAILABLE,tag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 24

发送状态:SLAVE_NOT_AVAILABLE,tag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 25

发送状态:SLAVE_NOT_AVAILABLE,tag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 26

发送状态:SLAVE_NOT_AVAILABLE,tag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 27

发送状态:SLAVE_NOT_AVAILABLE,tag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 28

发送状态:SLAVE_NOT_AVAILABLE,tag: TagC,队列ID: 3,消息体: 北京 Hello RocketMQ 29

 

Process finished with exit code 0

测试结果: 可正常生产30条数据

 

新创建topic 消费数据:

 

Consumer Started.

消费者2 ==> 当前线程:ConsumeMessageThread_1,storeHost: /10.3.14.237:10911,Tag: TagC ,quenuID: 3 ,content: 北京 Hello RocketMQ 20

消费者2 ==> 当前线程:ConsumeMessageThread_1,storeHost: /10.3.14.237:10911,Tag: TagC ,quenuID: 3 ,content: 北京 Hello RocketMQ 21

消费者2 ==> 当前线程:ConsumeMessageThread_1,storeHost: /10.3.14.237:10911,Tag: TagC ,quenuID: 3 ,content: 北京 Hello RocketMQ 22

消费者2 ==> 当前线程:ConsumeMessageThread_1,storeHost: /10.3.14.237:10911,Tag: TagC ,quenuID: 3 ,content: 北京 Hello RocketMQ 23

消费者2 ==> 当前线程:ConsumeMessageThread_1,storeHost: /10.3.14.237:10911,Tag: TagC ,quenuID: 3 ,content: 北京 Hello RocketMQ 24

消费者2 ==> 当前线程:ConsumeMessageThread_1,storeHost: /10.3.14.237:10911,Tag: TagC ,quenuID: 3 ,content: 北京 Hello RocketMQ 25

消费者2 ==> 当前线程:ConsumeMessageThread_1,storeHost: /10.3.14.237:10911,Tag: TagC ,quenuID: 3 ,content: 北京 Hello RocketMQ 26

消费者2 ==> 当前线程:ConsumeMessageThread_1,storeHost: /10.3.14.237:10911,Tag: TagC ,quenuID: 3 ,content: 北京 Hello RocketMQ 27

消费者2 ==> 当前线程:ConsumeMessageThread_1,storeHost: /10.3.14.237:10911,Tag: TagC ,quenuID: 3 ,content: 北京 Hello RocketMQ 28

消费者2 ==> 当前线程:ConsumeMessageThread_1,storeHost: /10.3.14.237:10911,Tag: TagC ,quenuID: 3 ,content: 北京 Hello RocketMQ 29

消费者2 ==> 当前线程:ConsumeMessageThread_2,storeHost: /10.3.14.237:10911,Tag: TagB ,quenuID: 2 ,content: 北京 Hello RocketMQ 10

消费者2 ==> 当前线程:ConsumeMessageThread_2,storeHost: /10.3.14.237:10911,Tag: TagB ,quenuID: 2 ,content: 北京 Hello RocketMQ 11

消费者2 ==> 当前线程:ConsumeMessageThread_2,storeHost: /10.3.14.237:10911,Tag: TagB ,quenuID: 2 ,content: 北京 Hello RocketMQ 12

消费者2 ==> 当前线程:ConsumeMessageThread_2,storeHost: /10.3.14.237:10911,Tag: TagB ,quenuID: 2 ,content: 北京 Hello RocketMQ 13

消费者2 ==> 当前线程:ConsumeMessageThread_2,storeHost: /10.3.14.237:10911,Tag: TagB ,quenuID: 2 ,content: 北京 Hello RocketMQ 14

消费者2 ==> 当前线程:ConsumeMessageThread_2,storeHost: /10.3.14.237:10911,Tag: TagB ,quenuID: 2 ,content: 北京 Hello RocketMQ 15

消费者2 ==> 当前线程:ConsumeMessageThread_2,storeHost: /10.3.14.237:10911,Tag: TagB ,quenuID: 2 ,content: 北京 Hello RocketMQ 16

消费者2 ==> 当前线程:ConsumeMessageThread_2,storeHost: /10.3.14.237:10911,Tag: TagB ,quenuID: 2 ,content: 北京 Hello RocketMQ 17

消费者2 ==> 当前线程:ConsumeMessageThread_2,storeHost: /10.3.14.237:10911,Tag: TagB ,quenuID: 2 ,content: 北京 Hello RocketMQ 18

消费者2 ==> 当前线程:ConsumeMessageThread_2,storeHost: /10.3.14.237:10911,Tag: TagB ,quenuID: 2 ,content: 北京 Hello RocketMQ 19

消费者2 ==> 当前线程:ConsumeMessageThread_3,storeHost: /10.3.14.237:10911,Tag: TagA ,quenuID: 1 ,content: 北京 Hello RocketMQ 0

消费者2 ==> 当前线程:ConsumeMessageThread_3,storeHost: /10.3.14.237:10911,Tag: TagA ,quenuID: 1 ,content: 北京 Hello RocketMQ 1

消费者2 ==> 当前线程:ConsumeMessageThread_3,storeHost: /10.3.14.237:10911,Tag: TagA ,quenuID: 1 ,content: 北京 Hello RocketMQ 2

消费者2 ==> 当前线程:ConsumeMessageThread_3,storeHost: /10.3.14.237:10911,Tag: TagA ,quenuID: 1 ,content: 北京 Hello RocketMQ 3

消费者2 ==> 当前线程:ConsumeMessageThread_3,storeHost: /10.3.14.237:10911,Tag: TagA ,quenuID: 1 ,content: 北京 Hello RocketMQ 4

消费者2 ==> 当前线程:ConsumeMessageThread_3,storeHost: /10.3.14.237:10911,Tag: TagA ,quenuID: 1 ,content: 北京 Hello RocketMQ 5

消费者2 ==> 当前线程:ConsumeMessageThread_3,storeHost: /10.3.14.237:10911,Tag: TagA ,quenuID: 1 ,content: 北京 Hello RocketMQ 6

消费者2 ==> 当前线程:ConsumeMessageThread_3,storeHost: /10.3.14.237:10911,Tag: TagA ,quenuID: 1 ,content: 北京 Hello RocketMQ 7

消费者2 ==> 当前线程:ConsumeMessageThread_3,storeHost: /10.3.14.237:10911,Tag: TagA ,quenuID: 1 ,content: 北京 Hello RocketMQ 8

消费者2 ==> 当前线程:ConsumeMessageThread_3,storeHost: /10.3.14.237:10911,Tag: TagA ,quenuID: 1 ,content: 北京 Hello RocketMQ 9

 

测试结果:可正常消费到30条数据。

 

集群Name Server高可用测试:

Name Server做的是Rocket的寻址服务, 用于将Broker的路由信息做聚合。客户端依靠Name Server决定去获取对应topic的路由信息,从而决定对那些Broker做链接。

Name Server是一个几乎无状态的节点, Name Server之间采用Share-Nothing的设计, 互不通信。

 

对于一个Name Server集群列表, 客户端链接Name Server的时候会随机选择一个节点, 以做到负载均衡。

Stop  10.3.14.11:9876的Name Server服务:

 

监控页面的Name Server 10.3.14.11:9876 更新、刷新后还在页面,应该是监控工具的BUG

 

如果生产客户端只连接了一个服务异常的Name Server,就会发生异常。不能send消息。

 

但消费端只连接了一个服务异常的Name Server的话,不会包报异常

 

如果客户端代码连接所有Name Server的话,可正常生产数据。

 

但连接了一个异常Name Server的消费客户端,数据无法正常消费到,也不会有异常:

 

集群消费客户端修改为连接所有的Name Server 可正常消费到上面生产的30条数据:

 

测试结论:

Name Server服务 相互之间无自动发现,且都无状态。为了客户端生产消费高可用建议代码中写入全部Name Server list所有服务。并且集群部署时Name Server服务尽量最好部署3个以上 保障高可用。

 

  1. 集群事务型消息生产代码和测试:

 

RocketMQLog:WARN Please initialize the logger system properly.

Fri Dec 13 16:46:28 CST 2019消息: 事务 message bj RocketMQ 0,Tag: TagA, SendResult [sendStatus=SLAVE_NOT_AVAILABLE, msgId=0A06CD6359492437C6DC4165C3210000, offsetMsgId=null, messageQueue=MessageQueue [topic=tx_t002, brokerName=broker-b, queueId=2], queueOffset=44]

Fri Dec 13 16:46:28 CST 2019消息: 事务 message bj RocketMQ 1,Tag: TagB, SendResult [sendStatus=SLAVE_NOT_AVAILABLE, msgId=0A06CD6359492437C6DC4165C3400001, offsetMsgId=null, messageQueue=MessageQueue [topic=tx_t002, brokerName=broker-b, queueId=3], queueOffset=45]

Fri Dec 13 16:46:28 CST 2019消息: 事务 message bj RocketMQ 2,Tag: TagC, SendResult [sendStatus=SLAVE_NOT_AVAILABLE, msgId=0A06CD6359492437C6DC4165C3470002, offsetMsgId=null, messageQueue=MessageQueue [topic=tx_t002, brokerName=broker-b, queueId=0], queueOffset=46]

Fri Dec 13 16:46:28 CST 2019消息: 事务 message bj RocketMQ 3,Tag: TagD, SendResult [sendStatus=SLAVE_NOT_AVAILABLE, msgId=0A06CD6359492437C6DC4165C34E0003, offsetMsgId=null, messageQueue=MessageQueue [topic=tx_t002, brokerName=broker-b, queueId=1], queueOffset=47]

Fri Dec 13 16:46:28 CST 2019消息: 事务 message bj RocketMQ 4,Tag: TagE, SendResult [sendStatus=SLAVE_NOT_AVAILABLE, msgId=0A06CD6359492437C6DC4165C3550004, offsetMsgId=null, messageQueue=MessageQueue [topic=tx_t002, brokerName=broker-b, queueId=2], queueOffset=48]

Fri Dec 13 16:46:28 CST 2019消息: 事务 message bj RocketMQ 5,Tag: TagA, SendResult [sendStatus=SLAVE_NOT_AVAILABLE, msgId=0A06CD6359492437C6DC4165C35B0005, offsetMsgId=null, messageQueue=MessageQueue [topic=tx_t002, brokerName=broker-b, queueId=3], queueOffset=49]

Fri Dec 13 16:46:28 CST 2019消息: 事务 message bj RocketMQ 6,Tag: TagB, SendResult [sendStatus=SLAVE_NOT_AVAILABLE, msgId=0A06CD6359492437C6DC4165C3620006, offsetMsgId=null, messageQueue=MessageQueue [topic=tx_t002, brokerName=broker-b, queueId=0], queueOffset=50]

Fri Dec 13 16:46:28 CST 2019消息: 事务 message bj RocketMQ 7,Tag: TagC, SendResult [sendStatus=SLAVE_NOT_AVAILABLE, msgId=0A06CD6359492437C6DC4165C3690007, offsetMsgId=null, messageQueue=MessageQueue [topic=tx_t002, brokerName=broker-b, queueId=1], queueOffset=51]

Fri Dec 13 16:46:28 CST 2019消息: 事务 message bj RocketMQ 8,Tag: TagD, SendResult [sendStatus=SLAVE_NOT_AVAILABLE, msgId=0A06CD6359492437C6DC4165C3700008, offsetMsgId=null, messageQueue=MessageQueue [topic=tx_t002, brokerName=broker-b, queueId=2], queueOffset=52]

Fri Dec 13 16:46:28 CST 2019消息: 事务 message bj RocketMQ 9,Tag: TagE, SendResult [sendStatus=SLAVE_NOT_AVAILABLE, msgId=0A06CD6359492437C6DC4165C3760009, offsetMsgId=null, messageQueue=MessageQueue [topic=tx_t002, brokerName=broker-b, queueId=3], queueOffset=53]

Process finished with exit code 0

 

集群模式消费端消费事务消息,没有消费到 也没有异常报错。

 

测试结论:

应该和集群主从模式配置有关,需要排查分析。

估计和发送消息返回状态sendStatus=SLAVE_NOT_AVAILABLE 有关。

5. RocketMQ生产端发送消息返回的4中状态:

SEND_OK, //状态成功,无论同步还是存储

FLUSH_DISK_TIMEOUT, // broker刷盘策略为同步刷盘(SYNC_FLUSH)的话时候,等待刷盘的时候超时

FLUSH_SLAVE_TIMEOUT, // master role采取同步复制策略(SYNC_MASTER)的时候,消息尝试同步到slave超时

SLAVE_NOT_AVAILABLE, //slave不可用

 

RocketMQ集群主从服务架构HA

 

  1. 目前社区版本存在问题
    目前RocketMQ集群主从模式,只要rocketmq master服务异常或服务器宕机,就会导致主从数据不一致。不管同步刷盘,还是异步刷盘都可能出现这种问题。
    异常场景:假如master服务宕机,消息不会往savle上写,这时候如果是异步刷盘,可能会导致,master,slave得数据不一直,salve可能会多比master多。当这个时候重启master,消费者会拿slave得消费进度去消费master得队列。导致出问题。
    存在问题:
    1.如何从新master上拉去消费进度
    2.主从数据一致性怎么保证?这时候savle得数据比master数据多。数据不一致,如果继续往master上写数据,会不会有问题?
    解决问题:
  2. 如何保障主从自动切换,且切换后服务依然可用(集群、生产、消费)
  3. 切换后,主从数据能保证一致性
  4. 社区版本主从自动切换技术方案:
    在 RocketMQ 4.5 版本之前,RocketMQ 只有 Master/Slave 一种部署方式,虽然这种模式可以提供一定的高可用性但也存在比较大的缺陷。为了实现新的高可用多副本架构,RockeMQ 最终选用了基于 Raft 协议的 commitlog 存储库 DLedger。
    基于 DLedger 的可以自动容灾切换的 RocketMQ 集群
    RocketMQ集群2m-2s-sync部署模式架构原理图:

 

在 RocketMQ 4.5 版本之前,RocketMQ 只有 Master/Slave 一种部署方式,一组 Broker 中有一个 Master,有零到多个 Slave,Slave 通过同步复制或异步复制方式去同步 Master 的数据。Master/Slave 部署模式,提供了一定的高可用性。

但这样的部署模式有一定缺陷。比如故障转移方面,如果主节点挂了还需要人为手动的进行重启或者切换,无法自动将一个从节点转换为主节点。因此,我们希望能有一个新的多副本架构,去解决这个问题。

新的多副本架构首先需要解决自动故障转移的问题,本质上来说是自动选主的问题。这个问题的解决方案基本可以分为两种:

利用第三方协调服务集群完成选主,比如 zookeeper 或者 etcd。这种方案会引入了重量级外部组件,加重部署,运维和故障诊断成本,比如在维护 RocketMQ 集群还需要维护 zookeeper 集群,并且 zookeeper 集群故障会影响到 RocketMQ 集群。

常用的分布式事务与一致性(选举)算法Paxos & raft & zab,其中zookeeper就用的zab原子广播协议,其实ZAB 也是在 Paxos 算法基础上进行扩展而来的。

利用 raft 协议来完成一个自动选主,raft 协议相比前者的优点,是它不需要引入外部组件,自动选主逻辑集成到各个节点的进程中,节点之间通过通信就可以完成选主。

因此最后选择用 raft 协议来解决这个问题,而 DLedger 就是一个基于 raft 协议的 commitlog 存储库,也是 RocketMQ 实现新的高可用多副本架构的关键。

DLedger 的其中一个应用就是在分布式消息系统中,RocketMQ 4.5 版本发布后,可以采用 RocketMQ on DLedger 方式进行部署。

DLedger commitlog 代替了原来的 commitlog,使得 commitlog 拥有了选举复制能力,然后通过角色透传的方式,raft 角色透传给外部 broker 角色,leader 对应原来的 Master,follower 和 candidate 对应原来的 Slave。

因此 RocketMQ 的 broker 拥有了自动故障转移的能力,如果在一组 broker 中,一个 Master 挂了以后,依靠 DLedger 自动选主的能力,会重新选出 leader,然后通过角色透传变成新的 Master。

目前没有集成DLedger,待部署

 

RocketMQ技术遗留和补充问题

 

  1. RocketMQ多主多从模式 从节点没有数据问题:
    RocketMQ中broker配置brokcerIP1和brokerIP2的作用
    brokerIP1 当前broker监听的IP
    brokerIP2 存在broker主从时,在broker主节点上配置了brokerIP2的话,broker从节点会连接主节点配置的brokerIP2来同步。
  2. 默认不配置brokerIP1和brokerIP2时,都会根据当前网卡选择一个IP使用,当你的机器有多块网卡时,很有可能会有问题。比如,我遇到的问题是我机器上有两个IP,一个公网IP,一个私网IP,结果默认选择的走公网IP,这是不正确的,我们期望的是所有业务内部通信都走内网。
    目前在阿里云服务器中就遇到了这个问题,没有配置brokerIP2,导致默认的公网IP,slave同步找不到,数据无法同步到过去。Slave节点始终没有数据。
  3. 需要先配置和创建相关数据和元数据的存储地址:如下
    #存储路径
    storePathRootDir=/data/rocketMQ-2m2s/store-s
    #commitLog 存储路径
    storePathCommitLog=/data/rocketMQ-2m2s/store-s/commitlog
    #消费队列存储路径存储路径
    storePathConsumeQueue=/data/rocketMQ-2m2s/store-s/consumequeue
    #消息索引存储路径
    storePathIndex=/data/rocketMQ-2m2s/store-s/index
    #checkpoint 文件存储路径
    storeCheckpoint=/data/rocketMQ-2m2s/store-s/checkpoint
    #abort 文件存储路径
    abortFile=/data/rocketMQ-2m2s/store-s/abort
    Master目录设置:

 

mkdir -p /data/rocketMQ-2m2s/store

mkdir -p /data/rocketMQ-2m2s/store/commitlog

mkdir -p /data/rocketMQ-2m2s/store/consumequeue

mkdir -p /data/rocketMQ-2m2s/store/index

mkdir -p /data/rocketMQ-2m2s/store/checkpoint

mkdir -p /data/rocketMQ-2m2s/store/abort

 

Slave目录设置:

mkdir -p /data/rocketMQ-2m2s/store-s

mkdir -p /data/rocketMQ-2m2s/store-s/commitlog

mkdir -p /data/rocketMQ-2m2s/store-s/consumequeue

mkdir -p /data/rocketMQ-2m2s/store-s/index

mkdir -p /data/rocketMQ-2m2s/store-s/checkpoint

mkdir -p /data/rocketMQ-2m2s/store-s/abort

 

  1. 集群模式 生产端SLAVE_NOT_AVAILABLE问题
    send数据 成功后,但返回的结果状态是:sendStatus=SLAVE_NOT_AVAILABLE,
    主要原因:
    1. Slave 没有同步到数据
      2.brokerRole=SYNC_MASTER之前为了提高性能采用ASYNC_MASTER机制,改成同步机制sync_master后返回状态是sendStatus=SEND_OK。 但其实SEND_OK并不一定代表着正常。
  1. 同一个Topic中多个队列在一个master borker上,不能多master并发和生产的HA保障

 

原因:

1.生产是默认的4个队列,没有路由到多个master上和多个队列级别的备份

2.rocketmq源码中默认在一个broker上路由4个或4的倍数的队列数,所有在创建队列数的时候需要注意这块问题

 

  1. 集群Master节点都异常不可用后,slave能正常支持消费端消费数据
  2. RocketMQ消息堆积对内存占用过大,消费端负载和性能问题(读写分离问题)
    RocketMQ的读写分离机制又跟上述描写的不太一致,RocketMQ 有属于自己的一套读写分离逻辑,它会判断主服务器的消息堆积量来决定消费者是否向从服务器拉取消息消费。
    slaveReadEnable 值来决定是否可以从从服务器拉取消息:

 

如果slaveReadEnable=true,并且堆积量已经超过物理内存 40%时,则建议从从服务器拉取消息,否则还是从主服务器拉取消息;

如果 slaveReadEnable=false,则消息者只能从主服务器中拉取消息。

 

  1. RocketMQ和spring集成方案:
    https://github.com/apache/rocketmq-spring
    Apache RocketMQ Spring Integration https://rocketmq.apache.org/
  2. benchmark集群压测和服务JVM heap问题
    目前测试集群  资源太小 benchmark 压测,比较吃力。
    ./producer.sh -t zs-cluster-001 -w 20 -s 1024 -n 10.3.14.11:9876;10.3.14.12:9876;10.3.14.241:9876
    20个线程并发 +每条1kb消息  一台机器 已经卡死。

 

nameserver 服务本身官方默认jvm 初始值 都给的8g 我们服务器资源太小 默认起不来 直接给了2g 但并发性能 肯定会影响,并发压测 也会受限。主要在runserver.sh中

 

broker节点服务的 jvm heap 也是一样。在runbroker.sh脚本中

看脚本里官方默认都用的G1 垃圾回收器,说明是期望在大堆栈环境中运行的,要不G1不一定比CMS 表现好。

中间件(二):MQ技术 1、技术调研应该怎么做? 技术调研:就是对一个技术去找到一些业内常用的开源实现,然后对各种不同的实现都进行一些调研,对比一下他们的优劣势,看看谁比较符合我们的需求,谁比较适合我们来使用。 具体来说,比如对于我们现在的情况,你只知道有一个MQ的概念,但是你要考虑一下: 业内常用的MQ有哪些? 每一种MQ各自的表现如何 ?MQ的优劣势? 这些MQ在同等机器条件下,能抗多少QPS(每秒抗几千QPS还是几万QPS)? 性能有多高(发送一条消息给他要2ms还是20ms)? 可用性能不能得... 阅读详情

相关推荐

FT601Q芯片深度解析:从USB3.0引脚定义到FPGA FIFO协议实战选型

本文深入解析FT601Q芯片在USB3.0接口设计与FPGA协议栈开发中的应用,详细介绍了USB3.0引脚定义、FT601Q芯片架构、245同步FIFO模式及硬件设计要点,帮助工程师实现高速数据传输系统。

weixin_30607659的博客 447

RocketMQ消息发送结果状态SLAVE_NOT_AVAILABLE

RocketMQ消息发送结果状态SLAVE_NOT_AVAILABLE 接上一篇博客《RocketMQ集群搭建(2m-2s-sync)及搭建中遇到的问题》,使用测试代码发送同步消息,返回结果SendResult中的消息状态sendStatus为SLAVE_NOT_AVAILABLE,从节点不可用。 从节点不可用,再结合集群的原理图,大致可以想到应该是生产者发送消息到broker主节点,主节点与从节点完成数据同步的时候出现了问题,,查看相关资料,最终定位到了brokerIP上。 上篇博客有说到过,198.1

qq_36816062的博客 3568

树莓派入门教程 - 0 - 准备篇 - 0.0 SD卡制作树莓派系统镜像启动盘 开机

电脑需要提前安装的工具: sd卡格式化工具SDFormatter,官网下载链接:https://www.sdcard.org/downloads/formatter/ 镜像烧录工具Win32 Disk Imager,官网下载链接:https://win32diskimager.download/ 使用到的硬件: 一张容量大于等于16GB的TF卡 + 读卡器; 树莓派板卡。3B、3B+、4B等各型号均可,带有 HDMI接口即可。 HDMI接口的显示屏。 鼠标、键盘、电脑。 1....

Mark_md的博客 6973

rocketMQ主从同步复制SLAVE_NOT_AVAILABLE找不到可用的从节点

brokerIP1 String Broker服务地址 brokerIP2 String BrokerHAIP地址,供slave同步消息的地址 我没有配置brokerIP2 , 导致一直找不到可用的从节点。 参数具体代表什么意思参考链接:https://blog.youkuaiyun.com/dianhe7741/article/details/101870269 ...

weixin_33623302的博客 2139

AHB不对称半桥反激电路设计(三)主要器件参数规格计算

本文介绍了AHB拓扑变压器的设计步骤与核心参数计算,包括主控芯片选择、工作原理分析及参数计算。作者选择DK87XXD集成MOS方案,详细阐述了输入电压范围、反射电压限定、匝比计算、工作频率设定、原副边电流值、电感量计算、磁芯选择、匝数计算、谐振电容设计等关键步骤。通过公式推导与实例计算,展示了150W电源的变压器设计过程,最终确定匝比5.5、原边22匝、副边4匝、电感量200uH等参数。文章还讨论了谐振电容与漏感的关系,为后续调试提供理论基础。该设计方法结合理论分析与工程实践,适用于AHB拓扑电源开发。

【Simon】的博客 3338

CMOS中的 latch-up 闩锁效应、添加tap解决latch-up、使用combained area绘制TAP TAP的作用 IC后端版图【VLSI】

本文详细阐述了闩锁效应latch-up问题、如何通过添加Tap来解决。详细讲述了如何通过combained area来绘制TAP

Jie_MSD的博客 1万+

RocketMQ的Consumer详解之push和pull模式(长轮询)

push和pull模式 在RocketMQ中,消费者有两种模式,一种是push模式,另一种是pull模式。 push模式:客户端与服务端建立连接后,当服务端有消息时,将消息推送到客户端。 pull模式:客户端不断的轮询请求服务端,来获取新的消息。 但在具体实现时,Push和Pull模式都是采用消费端主动拉取的方式,即consumer轮询从broker拉取消息。 区别: Push方...

Leon_Jinhai_Sun的博客 2403

基于深度学习的涂胶缺陷类型检测:数据集处理与YOLOv8模型实现

本文提出了一种基于YOLOv8深度学习的涂胶缺陷检测系统,针对断胶、溢胶、缺胶、气泡及胶条宽度异常等常见缺陷类型,实现了从数据采集到模型部署的完整解决方案。系统采用工业相机采集涂胶图像,通过多形态数据增强策略解决样本稀缺问题,利用YOLOv8框架实现高效检测。相比传统人工目检和规则式机器视觉方法,该系统在检测精度(mAP达97.5%)和实时性(单图检测耗时0.038秒)方面表现优异,可满足智能制造场景下的涂胶质量检测需求。

huanghm88的专栏 275

Rocketmq TIMEOUT_CLEAN_QUEUE源码追踪

1、问题现象 首先接到项目反馈使用 RocketMQ 会出现如下错误: 错误信息关键点:MQBrokerException:CODE:2 DESC:[TIMEOUT_CLEAN_QUEUE]broker busy,start flow control for a while,period in queue:205ms,size of queue:880。 由于项目组并没有对消息发送失败做任何补偿,导致丢失消息发送失败,故需要对这个问题进行深层次的探讨,并加以解决。 2、问题分析 首先我们根据关键字:

八荒六合唯我独尊 2359

C-08-实战:搭建一个AI客服机器人(接入微信企微)

客服是一人公司最大的时间杀手。本文教你搭建一个AI客服机器人,能自动回答80%的常见问题,只把复杂问题转给人工。含微信公众号和企业微信接入完整代码。

Johnny2004的专栏 88

少儿学编程系列--使用递归画出龙形曲线DragonCurve

龙形曲线(Dragon Curve) 龙形曲线(Dragon Curve)又叫分形龙,是一种自相似碎形曲线的统称,因形似龙的蜿蜒盘曲而得名 使用黄金比例画龙形曲线 根据黄金比例画一条龙曲线。每次递归,第一步向左转32.89度,移动0.74倍原距离;第二个递归步骤向右转46.99度,移动原来距离的0.55倍。请查看这个网页(https://larryriddle.agnesscott.org/ifs/heighway/goldenDragon.htm)了解关于龙形黄线数学的细节 龙形曲线效果 .

penriver的博客 2298

消息不丢失

大家好,我是君哥。 引入消息队列可以方便地实现系统解耦、削峰填谷等作用。但是消息队列使用不当,可能会引起消息丢失,在一些消息敏感的业务场景下,这是不允许的。今天我们来聊一聊 RocketMQ 怎么做能确保消息不丢失。 1 RocketMQ 简介 RocketMQ 是阿里巴巴开源的分布式消息中间件,整体架构如下图: RocketMQ 主要包括 Producer、Consumer 和 Broker,同时 Name Server 进行集群注册管理和保存元数据。 2 消息不丢失 要想保证消息不丢失,

to_real的博客 320

RK3568开发笔记- (TX/RX) RGMII delayline 功能调试

本文详细介绍了RK3568芯片RGMII接口delayline功能的调试过程。针对千兆以太网通信不稳定问题,通过分析RGMII时序要求,利用RK3568内置的delayline功能补偿信号延迟。调试方法包括扫描delayline窗口、测试中间值配置、优化硬件设计等步骤。文章还总结了常见问题解决方案,如PHY选型建议和自动扫描功能配置。最终实现了千兆速率下丢包率降至0.01%以下的目标,为类似开发场景提供了实用参考。

flypig has a dream! 318

Web前端最新常见的消息中间件有哪些?你们是怎么进行技术选型的?(1),前端最新大厂面试真题总结

正式学习前端大概 3 年多了,很早就想整理这个书单了,因为常常会有朋友问,前端该如何学习,学习前端该看哪些书,我就讲讲我学习的道路中看的一些书,虽然整理的书不多,但是每一本都是那种看一本就秒不绝口的感觉。我们先看ActiveMQ。它的社区还是很活跃的。我们来想一下,要在项目中使用一个新技术,是不是应该先了解市面上都有哪些常用的框架,所以应该从技术调研开始,选择合适的框架应用于我们的项目。以下大部分是我看过的,或者说身边的人推荐的书籍,每一本我都有些相关的推荐语,如果你有看到更好的书欢迎推荐呀。

2401_84619986的博客 766

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

谈谈 RocketMQ 5.0 分级存储背后一些有挑战的技术优化

RocketMQ 5.0 提出了分级存储的新方案,经过数个版本的深度打磨,RocketMQ 的分级存储日渐成熟,并成为降低存储成本的重要特性之一。事实上,几乎所有涉及到存储的产品都会尝试转冷降本,如何针对消息队列的业务场景去做一些有挑战的技术优化,是非常有意思的事。这篇文章就跟大家探讨下,在消息系统这样一个数据密集型应用的模型下,技术架构选型的分析与权衡,以及分级存储实现与未来演进,让云计算的资源...

HollisChuang's Blog 331

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

activemq的优势_为什么使用消息队列? 消息队列有什么优点和缺点? Kafka、ActiveMQ、RabbitMQ、RocketMQ 都有什么区别,以及适合哪些场景?...

面试官心理分析其实面试官主要是想看看:第一,你知不知道你们系统里为什么要用消息队列这个东西? 不少候选人,说自己项目里用了 Redis、MQ,但是其实他并不知道自己为什么要用这个东西。其实说白了,就是为了用而用,或者是别人设计的架构,他从头到尾都没思考过。 没有对...

weixin_39990410的博客 93

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

RocketMQ| 调研

一、 RocketMQ-介绍 二、 RocketMQ-组成结构 三、 RocketMQ-组成结构 RocketMQ组成结构图如下 : 交互过程如下: 1)Brokder定时发送自身状态 到NameServer。(保活) 2)Producer 请求NameServer获取Broker的地址。 3)Producer 将消息发送到Broker中的消息队列。 4)Consumer订阅Broker中的消息队列,通过拉取消息,或由Broker将消息推送至Consumer。 1)Producer Cluster 消息生产

YvesHe的专栏 598

RocketMQ调研笔记

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_33976072的博客 124

2020年,RocketMQ面试题 -面试题驱动RocketMQ学习

本文是《从 0 开始带你成为消息中间件实战高手》内容总结,版权问题,特此声明 本篇文章持续更新(星期1、3、5),大概有上百道题,用这些题来驱动RocketMQ学习,在面试中也会脱颖而出!! 15 解决订单系统诸多问题的核心技术:消息中间件到底是什么? 问1:什么是“同步”调用? 答: A、B、C三个系统,实现一个功能的调用链是:A调用B,B又调用C,A要返回结果,必须等B...

javaThinker的专栏 4万+

消息中间件:谈一谈 RocketMQ 的技术架构

RocketMQ 自阿里开源以来,在 Apache 下的孵化还不错,现在很多互联网公司都在生产环境下使用。当然也是各大技术厂商的面试要点。 技术架构 RocketMQ架构上主要分为四部分,如上图所示: Producer:消息发布的角色,支持分布式集群方式部署。Producer通过MQ的负载均衡模块选择相应的Broker集群队列进行消息投递,投递的过程支持快速失败并且低延迟。 Co...

编程者说的博客专栏 299

肝了亿遍还是吃不透RocketMQ?这份神仙RM笔记,让我佩服的五体投地

最近公司急招架构师,形形色色的人面了很多,但真正懂得设计思维的真的是少之又少。印象最深刻的一个同学,面对我提问的这个问题的时候,回答真的是让我佩服的五体投地! 问:“你们公司为什么会选择用RocketMQ,而不是ActiveMQ、RabbitMQ?” 当时他给我的答案是:当时领导决定的! 一个用消息队列好几年的人,却不知道它的工作原理,也没有评估引入这些不同的组件会给项目带来何种风险的意识,不知道这样的人是怎样有勇气来面试架构师的!但其实,这样的同学还真是不在少数! 其实,一家公司在引入基础组件时,需要根.

weixin_47083537的博客 188

始于架构,精于治理|阿里云中间件开发者大会火热报名中

6 月 16 日,主题为“始于架构、精于治理”的阿里云首届中间件开发者大会将在线上进行直播。

阿里巴巴中间件 334

Kafka、RabbitMQ以及RocketMQ的调研对比

Kafka、RabbitMQ以及RocketMQ的调研对比 一般国内常用的MQ技术有四种实现,ActiveMQ、Kafka、RabbitMQ、RocketMQ,但是其中 ActiveMQ主要是几年以前较多公司使用,现在几乎国内用的公司都很少了。 (1)Kafka的优势和劣势 先来说Kafka,首先Kafka的吞吐量几乎是行业里最优秀的,在常规的机器配置下,一台机器 可以达到每秒十几万的QPS,相当的强悍。 以继续运行的。Kafka性能也很高,基本上发送消息给Kafka都是毫秒级的性能.

weixin_47247523的博客 619

实习第二十九天日记周四【2026.8.13】

昨日工作:对应功能已部署至平台并完成测试;主任反馈审批流程、需求存在变更调整,当前暂停该模块开发,转做低代码平台页面接入工作。待办:等待需求更新后再迭代原有部署功能。15:00-15:30周报15:30-16:00总结复习16:00-17:30解决相关软件的问题,学习相关软件。记得还要把单词背了。

2303_80799640的博客 172

阿里技术官整合的四大主流中间件笔记,让你高薪摸鱼,不再秃头背锅

目前,消息队列在各大互联网平台,尤其是电商平台如京东、淘宝、去哪儿等网站有着深入的应用,主要作用是高并发访问高峰,通过异步消息模式减少网站响应时间,提高系统吞吐量。小编这期的专题总结市面上不常见到的技术点拉满的四大主流消息中间件学习笔记,归类整理了MQ(ActiveMQ/RabbitMQ/RocketMQ)+Kafka等的纯手写的实战+原理整合笔记,我们来想一下,要在项目中使用一个新技术,是不是应该先了解市面上都有哪些常用的框架,所以应该从技术调研开始,选择合适的框架应用于我们的项目。

jjc4261的博客 1084

rocketmq 消费方式_【解构云原生】RocketMQ高可用方案调研及On K8S设计展望(上)...

本文由作者授权网易云发布,未经许可,请勿转载。作者:李海燕,网易杭州研究院云计算技术部工程师一、前言RocketMQ是阿里捐赠给Apache并于2018年作为顶级项目孵化的分布式消息引擎,目前已经加入CNCF成为云原生核心消息中间件。国内厂商如美团,滴滴、爱奇艺、顺丰和民生银行等都在使用,网易集团内部云音乐和严选也在使用RocketMQ,并对周边功能进行了扩展定制。鉴于RocketMQ的广泛使用,...

weixin_39926042的博客 167
上一篇: Kerberos+HDP客户端部署与配置
下一篇: Ranger1.2.1+LDAP bug fix
那年夏天110
博客等级 码龄16年 2粉丝 12原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值