core节点宕机后,repl节点消息队列积压

集群情况,一个 core 节点,两个 repl 节点,k8s部署,core和repl分开在两个workload部署

其中有一个 repl 节点 (下称A节点) 之前宕机过一次,emqx_mria_lag 值变为 -8, 当时发帖询问过,message_queue_len和replayq_len为0的情况不需要人为干预,emqx_mria_server_mql基本也维持在0, 当时咨询得到的答复是,后期 repl 节点会自动 bootstrap+追平,不过后面没有额外的人为操作,lag值一直维持在-8,其他指标也没变化过,也没有追平

前几天 core 节点因为云厂商的问题宕机过一次,宕机约 10-15min,宕机后,A节点的emqx_delivery_dropped_queue_full 值从0变为11, emqx_mria_lag 从 -8 变为-7865
emqx eval 'mria_rlog:status().' 的输出结果是(已做脱敏处理):

#{role => replicant,backend => rlog,shards_down => [],
  shard_stats =>
      #{'$mria_meta_shard' =>
            #{message_queue_len => 0,state => normal,
              upstream =>
                  'emqx-aaaaaaa@emqx-ev-xxxx-yyyyy.svc.cluster.local',
              bootstrap_num_keys => 3,bootstrap_time => 115,lag => 0,
              last_imported_trans => 28,replayq_len => 0},
        emqx_common_shard =>
            #{message_queue_len => 0,state => normal,
              upstream =>
                  'emqx-aaaaaaa@emqx-ev-xxxx-yyyyy.svc.cluster.local',
              bootstrap_num_keys => 7,bootstrap_time => 90,lag => 0,
              last_imported_trans => 2,replayq_len => 0},
        emqx_cm_shard =>
            #{message_queue_len => 0,state => normal,
              upstream =>
                  'emqx-aaaaaaa@emqx-ev-xxxx-yyyyy.svc.cluster.local',
              bootstrap_num_keys => 23,bootstrap_time => 120,lag => -4105,
              last_imported_trans => 3629233,replayq_len => 0},
        emqx_exclusive_shard =>
            #{message_queue_len => 0,state => normal,
              upstream =>
                  'emqx-aaaaaaa@emqx-ev-xxxx-yyyyy.svc.cluster.local',
              bootstrap_num_keys => 1,bootstrap_time => 3,lag => 0,
              last_imported_trans => 0,replayq_len => 0},
        route_shard =>
            #{message_queue_len => 0,state => normal,
              upstream =>
                  'emqx-aaaaaaa@emqx-ev-xxxx-yyyyy.svc.cluster.local',
              bootstrap_num_keys => 5,bootstrap_time => 54,lag => -248,
              last_imported_trans => 3304603,replayq_len => 0},
        emqx_shared_sub_shard =>
            #{message_queue_len => 0,state => normal,
              upstream =>
                  'emqx-aaaaaaa@emqx-ev-xxxx-yyyyy.svc.cluster.local',
              bootstrap_num_keys => 1,bootstrap_time => 3,lag => 0,
              last_imported_trans => 769,replayq_len => 0},
        emqx_cluster_rpc_shard =>
            #{message_queue_len => 0,state => normal,
              upstream =>
                  'emqx-aaaaaaa@emqx-ev-xxxx-yyyyy.svc.cluster.local',
              bootstrap_num_keys => 3,bootstrap_time => 5,lag => 0,
              last_imported_trans => 3,replayq_len => 0},
        emqx_authn_shard =>
            #{message_queue_len => 0,state => normal,
              upstream =>
                  'emqx-aaaaaaa@emqx-ev-xxxx-yyyyy.svc.cluster.local',
              bootstrap_num_keys => 3,bootstrap_time => 6,lag => 0,
              last_imported_trans => 1,replayq_len => 0},
        emqx_acl_sharded =>
            #{message_queue_len => 0,state => normal,
              upstream =>
                  'emqx-aaaaaaa@emqx-ev-xxxx-yyyyy.svc.cluster.local',
              bootstrap_num_keys => 1,bootstrap_time => 3,lag => 0,
              last_imported_trans => 0,replayq_len => 0},
        emqx_dashboard_shard =>
            #{message_queue_len => 0,state => normal,
              upstream =>
                  'emqx-aaaaaaa@emqx-ev-xxxx-yyyyy.svc.cluster.local',
              bootstrap_num_keys => 3,bootstrap_time => 6,lag => 0,
              last_imported_trans => 1,replayq_len => 0},
        emqx_retainer_shard =>
            #{message_queue_len => 0,state => normal,
              upstream =>
                  'emqx-aaaaaaa@emqx-ev-xxxx-yyyyy.svc.cluster.local',
              bootstrap_num_keys => 6,bootstrap_time => 10,lag => -9,
              last_imported_trans => 325735,replayq_len => 0},
        emqx_psk_shard =>
            #{message_queue_len => 0,state => normal,
              upstream =>
                  'emqx-aaaaaaa@emqx-ev-xxxx-yyyyy.svc.cluster.local',
              bootstrap_num_keys => 1,bootstrap_time => 3,lag => 0,
              last_imported_trans => 0,replayq_len => 0},
        emqx_telemetry_shard =>
            #{message_queue_len => 0,state => normal,
              upstream =>
                  'emqx-aaaaaaa@emqx-ev-xxxx-yyyyy.svc.cluster.local',
              bootstrap_num_keys => 2,bootstrap_time => 3,lag => 0,
              last_imported_trans => 1,replayq_len => 0}},
  shards_in_sync =>
      ['$mria_meta_shard',emqx_acl_sharded,emqx_authn_shard,
       emqx_cluster_rpc_shard,emqx_cm_shard,emqx_common_shard,
       emqx_dashboard_shard,emqx_exclusive_shard,emqx_psk_shard,
       emqx_retainer_shard,emqx_shared_sub_shard,emqx_telemetry_shard,
       route_shard]}

截至发稿前,另一个repl节点也出现了 emqx_delivery_dropped_queue_full 突增的情况,从 0 升至 95,看了一下监控,中间有大约半小时没有消息接收,也在这半小时里出现丢弃消息数剧增

看了下目前业务上的一些订阅,有部分已使用共享订阅,当前最大消息队列长度为 1k,当前消息匹配速率:发布和接收速率大概在100条/秒 以内

现在有几个概念想理清楚,

  • emqx_delivery_dropped_queue_full 这个值是一个历史结果值还是指当前的队列满丢弃数,这个值能否通过人为操作降为 0,
  • 针对这种情况,有没有什么人为操作能恢复节点滞后性、队列满丢弃的现象

mria_rlog:status 里各 shard 的 lag/message_queue_len/replayq_len 都是 0,说明 A 节点已经追平了。emqx_mria_lag 负值一直不变更像是指标抓错节点或时序没刷新,不是复制没追平。
先确认 Prometheus target 是不是直连 A 节点的 Pod,别用 Service 负载均衡打到 core。很多人因为采集打到 core,看到的 lag 其实不是 A 节点。
把下面信息贴一下:

  • A 节点的 EMQX 版本(emqx ctl broker)
  • A 节点执行 emqx ctl eval ‘mria_lb:core_nodes().’ 的输出
  • A 节点的 emqx_mria_lag 指标行(含 instance/pod 标签),确认采集目标
    另外 emqx_delivery_dropped_queue_full=11 是会话投递队列满导致丢弃。要继续排查的话贴下这几个配置和客户端参数:
  • zone.external.mqueue.max_len
  • zone.external.mqtt.max_inflight / max_awaiting_rel
  • 客户端 QoS / Receive Maximum
  • 看了下 prometheus 确实直接采集的 core,从 core 拉取的指标里有显示 repl 的 lag 指标
  • emqx ctl broker version: 5.7.2 (3 个节点都是相同的版本)
  • emqx eval 'mria_lb:core_nodes().' 的输出是 core 节点的相关信息,具体需要对部分 id 脱敏 ['emqx-ev-xxxxxx@emqx-ev-xxxxxx-emqx-event-core-0.emqx-ev-xxxxxx-emqx-event-headless.ks-bd-aaaa-prod-yyyy-xxxx-003.svc.cluster.local']
  • 关于 emqx_mria_lag 的指标行,确认了 pod/node 标签,确认两个 repl 节点均有 lag 负值
  • zone.external.mqueue.max_len=1000 (最大消息队列长度)
  • zone.external.mqtt.max_inflight=32 (最大飞行窗口)
  • zone.external.max_awaiting_rel=100 (最大待发 PUBREL 数量)
  • 客户端接收消息速率在 70-95条/秒,最大值在 100 (近 7 天监控数据)
  • 以 rlog:status 为准,不需要人为 bootstrap。
  • core 宕机/重启后 emqx_mria_lag 出现负值很常见,5.7.2 里更像是指标计算问题,建议升级到 5.7.x 最新 patch 看是否恢复。
  • emqx_delivery_dropped_queue_full=11 是会话投递队列满丢弃(非 QoS0),和 mria lag 无关。要减少丢弃就调大 mqueue.max_len / max_inflight / max_awaiting_rel,或让客户端更快 ack。
    还想继续追的话补这两项:
  1. 两个 repl 各自的 emqx_mria_server_mql 曲线(有没有持续增长)
  2. drop 发生时段的 emqx.log 里是否有 queue_full / slow subscriber 的日志
  • 官方文档里对于 emqx_mria_server_mql 指标的说明:等待发送至复制节点的未处理的事务数量,仅 core 节点有,最近 15 天里 core 节点 emqx_mria_server_mql 都为 0
  • A节点的日志里有类似的 2026-02-25T23:31:28.157652533+08:00 2026-02-25T15:31:28.157282+00:00 [warning] clientid: xxxxxx, msg: dropped_msg_due_to_mqueue_is_full, peername: 10.32.13.208:41032, username: dev-event-consumer, topic: $dev/xxxx/xxx/event/pecker/Conn, queue: #{len => 1000,dropped => 1,store_qos0 => true,max_len => 1000}, payload:

rlog:status 各 shard lag=0 就是追平了,emqx_mria_lag 负值是 5.7.2 指标计算问题,升级到 5.7.x 最新 patch 或先忽略这个指标。
dropped_msg_due_to_mqueue_is_full 是会话投递队列满导致丢弃,和 mria 无关,本质是消费端慢/离线积压。
可以先这样处理:

  1. 如果允许丢 QoS0,关掉存储:zone.external.mqtt.mqueue_store_qos0 = false
  2. 需要保留就把队列拉大:zone.external.mqueue.max_len = 5000 或更高
  3. 放大飞行窗口:zone.external.mqtt.max_inflight / max_awaiting_rel(同时确认客户端 Receive Maximum 也提高)
  4. 高频 topic 用共享订阅或限流
    再补两项我看一下:客户端的 Receive Maximum / ACK RTT、以及这个 clientid 是否频繁断连或多实例共用。