rocketmq

RocketMQ

业务考量

  • 削峰
    • Producer->MQ 的吞吐量
    • MQ-> Consumer的吞吐量
  • 解耦
    • 一对多的消息传递

启动

  • 修改启动命令的Xms和Xmx

    • bin/runserver.sh
    • bin/ runbroker.sh
  • broker所在 机器配置指向namesrv的环境变量

    export NAMESRV_ADDR='localhost:9876'

  • 启动namesrv 和broker

    • nohup bin/mqnamesrv &
    • nohup bin/mqbroker &
  • 测试发送和消费

    #发1000条
    bin/tools.sh org.apache.rocketmq.example.quickstart.Producer
    #SendResult [sendStatus=SEND_OK, msgId=C0A876B41AC3421104065E5F0A4B03E7, offsetMsgId=C0A876B400002A9F000000000003AFF0, messageQueue=MessageQueue [topic=TopicTest, brokerName=localhost.localdomain, queueId=2], queueOffset=249, recallHandle=null]
    
    #消费
    bin/tools.sh org.apache.rocketmq.example.quickstart.Consumer
    # ConsumeMessageThread_please_rename_unique_group_name_4_7 Receive New Messages: [MessageExt [brokerName=localhost.localdomain, queueId=3, storeSize=242, queueOffset=197, sysFlag=0, bornTimestamp=1781880486461, bornHost=/192.168.118.180:49648, storeTimestamp=1781880486462, storeHost=/192.168.118.180:10911, msgId=C0A876B400002A9F000000000002E87A, commitLogOffset=190586, bodyCRC=1116443590, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message{topic='TopicTest', flag=0, properties={CONSUME_START_TIME=1781880681810, MSG_REGION=DefaultRegion, UNIQ_KEY=C0A876B41AC3421104065E5F08BD0314, CLUSTER=DefaultCluster, MIN_OFFSET=0, TAGS=TagA, WAIT=true, TRACE_ON=true, MAX_OFFSET=250}, body=[72, 101, 108, 108, 111, 32, 82, 111, 99, 107, 101, 116, 77, 81, 32, 55, 56, 56], transactionId='null'}]]
    
    

集群架构

普通集群

  • NameServer集群
    • 高可用
  • Broker集群+主从
    • 性能提升 + 备份
    • 不具备高可用(一个broker宕机,消息全部进入其他broker)
  • 集群规划
机器 nameServer部署 broker部署
worker1 nameServer broker1,broker2-s
worker2 nameServer broker2,broker1-s
worker3 nameServer

Dledger集群

broker:leader+ follower

leader接受请求,转发到其他broker(follower)

测试:docker部署

机器 nameServer部署(端口) broker部署(端口) dashboard
worker1 nameServer (9877) broker1(10911) dashboard (18082)
worker2 nameServer(9878) broker2(10921)
worker3 nameServer(9879) broker3(10931)
  • 配置

    #1.为每个节点创建独立的docker挂载出的配置、数据、日志和存储目录。
    # 创建根目录
    mkdir -p /opt/rocketmq-dledger
    cd /opt/rocketmq-dledger
    # 循环创建 3 个 NameServer 和 3 个 Broker 的目录
    for i in 1 2 3; do
      mkdir -p nameserver${i}/logs nameserver${i}/store
      mkdir -p broker${i}/logs broker${i}/store broker${i}/conf
    done
    
    #2.写broker.conf,配置dledger集群
    #2.1
    vi /opt/rocketmq-dledger/broker1/conf/ 	
    
    brokerClusterName = RaftCluster
    brokerName=RaftNode00
    brokerIP1=192.168.118.180
    listenPort=10911
    namesrvAddr=192.168.118.180:9877;192.168.118.180:9878;192.168.118.180:9879
    enableDLegerCommitLog=true
    dLegerGroup=RaftNode00
    dLegerPeers=n0-192.168.118.180:10913;n1-192.168.118.180:10923;n2-192.168.118.180:10933
    dLegerSelfId=n0
    sendMessageThreadPoolNums=16
    
    #2.2 
    vi /opt/rocketmq-dledger/broker2/conf/broker.conf
    
    brokerClusterName = RaftCluster
    brokerName=RaftNode00
    brokerIP1=192.168.118.180
    listenPort=10921
    namesrvAddr=192.168.118.180:9877;192.168.118.180:9878;192.168.118.180:9879
    enableDLegerCommitLog=true
    dLegerGroup=RaftNode00
    dLegerPeers=n0-192.168.118.180:10913;n1-192.168.118.180:10923;n2-192.168.118.180:10933
    dLegerSelfId=n1
    sendMessageThreadPoolNums=16
    
    #2.3
    vi /opt/rocketmq-dledger/broker3/conf/broker.conf
    
    brokerClusterName = RaftCluster
    brokerName=RaftNode00
    brokerIP1=192.168.118.180
    listenPort=10931
    namesrvAddr=192.168.118.180:9877;192.168.118.180:9878;192.168.118.180:9879
    enableDLegerCommitLog=true
    dLegerGroup=RaftNode00
    dLegerPeers=n0-192.168.118.180:10913;n1-192.168.118.180:10923;n2-192.168.118.180:10933
    dLegerSelfId=n2
    sendMessageThreadPoolNums=16
    
    #3 执行以下命令,把所有 broker 和 nameserver 目录的所有权交给 UID 3000:
    cd /opt/rocketmq-dledger
    chown -R 3000:3000 ./broker1 ./broker2 ./broker3 ./nameserver1 ./nameserver2 ./nameserve
    
    
    1. 创建docker-compose.yml
    container_name: broker1
    restart: always
    ports:
      - "10911:10911"
      - "10911:10911/udp"
      - "10912:10912"
      - "10909:10909"
      - "10913:10913"
    volumes:
      - ./broker1/logs:/home/rocketmq/logs
      - ./broker1/store:/home/rocketmq/store
      - ./broker1/conf/broker.conf:/home/rocketmq/rocketmq-5.5.0/conf/broker.conf
    environment:
      - JAVA_OPT_EXT=-server -Xms256m -Xmx256m
    command: sh mqbroker -c /home/rocketmq/rocketmq-5.5.0/conf/broker.conf -n "192.168.118.180:9877;192.168.118.180:9878;19
2.168.118.180:9879"
    depends_on:
      - nameserver1
      - nameserver2
      - nameserver3

  broker2:
    image: apache/rocketmq:5.5.0
    container_name: broker2
    restart: always
    ports:
      - "10921:10921"
      - "10921:10921/udp"
      - "10922:10922"
      - "10919:10919"
      - "10923:10923"
    volumes:
      - ./broker2/logs:/home/rocketmq/logs
      - ./broker2/store:/home/rocketmq/store
      - ./broker2/conf/broker.conf:/home/rocketmq/rocketmq-5.5.0/conf/broker.conf
    environment:
      - JAVA_OPT_EXT=-server -Xms256m -Xmx256m
    command: sh mqbroker -c /home/rocketmq/rocketmq-5.5.0/conf/broker.conf -n "192.168.118.180:9877;192.168.118.180:9878;192.168.118.180:9879"
    depends_on:
      - nameserver1
      - nameserver2
      - nameserver3

  broker3:
    image: apache/rocketmq:5.5.0
    container_name: broker3
    restart: always
    ports:
      - "10931:10931"
      - "10931:10931/udp"
      - "10932:10932"
      - "10929:10929"
      - "10933:10933"
    volumes:
      - ./broker3/logs:/home/rocketmq/logs
      - ./broker3/store:/home/rocketmq/store
      - ./broker3/conf/broker.conf:/home/rocketmq/rocketmq-5.5.0/conf/broker.conf
    environment:
      - JAVA_OPT_EXT=-server -Xms256m -Xmx256m
    command: sh mqbroker -c /home/rocketmq/rocketmq-5.5.0/conf/broker.conf -n "192.168.118.180:9877;192.168.118.180:9878;192.168.118.180:9879"
    depends_on:
      - nameserver1
      - nameserver2
      - nameserver3
  #=================================dashboard=====================
  dashboard:
    image: apacherocketmq/rocketmq-dashboard:latest
    container_name: rocketmq-dashboard
    restart: always
    ports:
      - "8082:8082"
    environment:
      - JAVA_OPTS=-Drocketmq.namesrv.addr=192.168.118.180:9877;192.168.118.180:9878;192.168.118.180:9879 -Dcom.rocketmq.sendMessageWithVIPChannel=false
    volumes:
      - /etc/localtime:/etc/localtime:ro

启动集群

cd /opt/rocketmq-dledger
docker-compose up -d

查看日志

docker-compose logs -f broker1

停止并清理集群(保留数据):

docker-compose down

Controller集群

DashBoard设置

Topic设置

  • 类型:普通、FIFO、事务、延迟
  • 队列数量
  • perm:权限

ConsumerGroup设置

除了广播消费外,其他设置都以客户端ConsumerGroup配置为准

  • 是否广播消费:(默认集群消费)

    广播消费优先级最高。dashboard中和客户端中,任一配置为广播消费,则是广播消费。

    • 集群模式下,消费offset由broker端管理,多个consumer共同消费
    • 广播模式下,offset由consumer自行保管,每个consumer都消费所有消息
  • 是否有序消费:(默认无序)

  • 重试队列数量,默认1

  • 最大重试次数,默认16

消息过滤

broker.conf 添加参数 enablePropertyFilter=true

  • 简单过滤

    生产者发送。设置tag
    consumer订阅topic时。subExpression中写规则,
    - “*” 所有
    - “TAG1 || TAG3” 多个
    
  • sql过滤

    生产者发送,设置Propperty
    consumer订阅时,添加 FilterExpression 
    

消息机制

消息确认机制


//2.生产者->MQ
/*DefaultMQProducer.send方法  
同步、异步 两种
SendResult中 sendStatus=SEND_OK表示发送成功
*/
 public SendResult send(Message msg)
 public void send(Message msg, SendCallback sendCallback) 
     
         
//3.MQ->消费者    
/*
DefaultMQPushConsumer.registerMessageListener监听中返回状态 进行消费确认。
MessageListenerOrderly和ConsumeConcurrently 串行和并行两种消费类型

ConsumeOrderlyStatus.SUCCESS 消费成功  SUSPEND_CURRENT_QUEUE_A_MOMENT  暂停队列拉取,一会进行重试
ConsumeConcurrentlyStatus.CONSUME_SUCCESS 消费成功  RECONSUME_LATER 稍后重新消费

*/     

     

顺序消息机制

场景:有序事件处理、撮合交易、数据实时增量同步

  • 相同消息组的消息按照先后顺序被存储在同一个队列。
  • 不同消息组的消息可以混合在同一个队列中,且不保证连续
  • 生产顺序性
    • 单一生产者
    • 串行发送
    • 消息上设置相同消息组(MessageGroup),为了确保进入同一个MessageQueue
  • 消费顺序性
    • 投递顺序
      • PushConsumer:按照存储顺序一条一条投递给消费者
      • SimpleConsumer:消息消费的顺序性需要由业务方自行保证
    • 使用MessageListenerOrderly
    • 有限重试

定时消息

  • 消息被发送至服务端后,在指定时间后才能被消费者消费

  • 定时时长最大值默认为24小时,超过范围则定时不生效,服务端会立即投递消息

  • 定时消息仅支持在 MessageType为**Delay **的主题内使用、

  • 使用场景:

    • 分布式定时调度(24h内)
    • 任务超时处理
  • //设置定时推送到Consumer
    message.setDeliverTimeMs(timeMs);
    //设置延迟多久推送到Consumer 18种级别: 1s 5s 10s 30s 1min 2 3 4 5  ...1h 2h
    message.setDelayTimeLevel(3);//10s
    

批量消息

  • 生产者批量发送
//维护一个messages,一次发送。
List<Message> messages;
//ListSplitter 为了将大List拆分
  ListSplitter splitter = new ListSplitter(messages);
        while (splitter.hasNext()) {
            List<Message> listItem = splitter.next();
            SendResult sendResult = producer.send(listItem);
            System.out.printf("%s", sendResult);
        }

事务消息机制

消息可靠性

消息不丢失

  • producer->MQ

    • 同步发送+多次尝试:io降低
    • 事务消息机制: 多次网络请求
  • Broker消息不丢失

    • 同步刷盘:io负担
    • DLedger集群:自动故障切换、极高数据可靠、写入性能较低、高网络IO
    • Controller集群+同步刷盘:秒级自动故障切换、数据高可靠、写入性能接近原生主从、
  • MQ->consumer

    • 同步处理消息,再提交offset
  • MQ集群挂了

    • 增加临时降级存储
  • 关注重试队列 和 死信队列,对死信队列单独唯独维护 消费者。

消息顺序性

  • 生产顺序性
    • 单一生产者
    • 串行发送
    • 消息上设置相同消息组(MessageGroup),为了确保进入同一个MessageQueue
  • 消费顺序性
    • 投递顺序
      • PushConsumer:按照存储顺序一条一条投递给消费者
      • SimpleConsumer:消息消费的顺序性需要由业务方自行保证
    • 使用MessageListenerOrderly
    • 有限重试

消息幂等性

  • 生产者发送
    • 发送消息时,自动分配唯一id。重试发送时,自己会校验
  • 消费者消费
    • 通过指定业务id作为key,判断是否已经消费过。

快速处理消息积压

  • 判断消费卡点,有没有能优化的地方

  • 5.x,加Consumer即可

  • 4.x 加customer,但数量<=messagequeue,极端 情况下要 新建topic,创建多messagequeue,之后消费新topic中的

其他问题

  • RocketMQ消费消息是推模式还拉模式
    • 推模式:长轮训,拉取
  • RocketMQ消息是如何存储的
    • commitlog
    • consumeroffsit
    • indexFile
  • RocketMQ生产环境如何优化
    • 生产者

      • 批量发送、异步发送
      • 合理设置超时时间
    • 消费者

      • 增加消费线程数 setConsumeThreadMax/Min
      • 批量消费 setConsumeMessageBatchMaxSize()
      • 合理设置重试次数
    • Broker

      • 增加Broker和MessageQueue数量
      • 主从异步复制、异步刷盘
      • 消费者设置长轮训
      • jvm 堆内存大小,垃圾收集器选择G1
    • 其他

      • 消息存储优化:文件预热设置
      • 监控告警
      • 消息压缩 message.setCompressed(true);
posted @ 2026-06-25 10:33  赵钱富贵  阅读(8)  评论(0)    收藏  举报