Skip to content
清晨的一缕阳光
返回

RocketMQ DLedger 实战指南

RocketMQ DLedger 是基于 Raft 协议的高可用存储方案,提供自动主从切换、强一致性保证。本文将深入探讨 DLedger 的原理、配置和实战。

一、DLedger 架构

1.1 架构演进

主从模式

graph TB
    subgraph Broker 集群
        M[Master]
        S1[Slave 1]
        S2[Slave 2]
    end
    
    M -->|同步复制 | S1
    M -->|同步复制 | S2
    
    P[Producer] --> M
    C[Consumer] --> M

DLedger 模式

graph TB
    subgraph DLedger Group
        L[Leader]
        F1[Follower 1]
        F2[Follower 2]
    end
    
    L -.->|Raft | F1
    L -.->|Raft | F2
    
    P[Producer] --> L
    C[Consumer] --> L

1.2 核心优势

优势说明
自动切换Leader 宕机自动选举
强一致性Raft 协议保证
数据可靠多数派确认
运维简单无需手动切换

1.3 模式对比

特性主从模式DLedger 模式
切换手动/半自动自动
一致性最终一致强一致
可靠性
性能
适用场景一般业务金融场景

二、Raft 协议

2.1 Raft 基础

Raft 协议核心:
1. Leader 选举
2. 日志复制
3. 安全性保证

2.2 Leader 选举

sequenceDiagram
    participant N1 as Node 1
    participant N2 as Node 2
    participant N3 as Node 3
    
    N1->>N1: 启动,成为 Follower
    N2->>N2: 启动,成为 Follower
    N3->>N3: 启动,成为 Follower
    
    N1->>N2: Request Vote (Term 1)
    N1->>N3: Request Vote (Term 1)
    N2-->>N1: Vote Yes
    N3-->>N1: Vote Yes
    
    N1->>N1: 成为 Leader
    N1->>N2: 心跳
    N1->>N3: 心跳

2.3 日志复制

graph TB
    subgraph Leader
        L1[日志条目 1]
        L2[日志条目 2]
        L3[日志条目 3]
    end
    
    subgraph Follower 1
        F1[日志条目 1]
        F2[日志条目 2]
    end
    
    subgraph Follower 2
        FF1[日志条目 1]
        FF2[日志条目 2]
        FF3[日志条目 3]
    end
    
    L1 --> F1
    L1 --> FF1
    L2 --> F2
    L2 --> FF2
    L3 --> FF3

三、DLedger 配置

3.1 Broker 配置

# broker.conf

# 启用 DLedger
enableDLegerCommitLog=true

# DLedger 组名
dLegerGroup=DefaultDledgerGroup

# DLedger 节点配置
dLegerPeers=n0-192.168.1.10:9878;n1-192.168.1.11:9878;n2-192.168.1.12:9878

# 当前节点 ID
dLegerSelfId=n0

# 存储路径
storePathRootDir=/data/rocketmq/store
storePathCommitLog=/data/rocketmq/store/dledger

# 监听端口
listenPort=10911

3.2 多节点配置

节点 0

# broker-n0.conf
enableDLegerCommitLog=true
dLegerGroup=DefaultDledgerGroup
dLegerPeers=n0-192.168.1.10:9878;n1-192.168.1.11:9878;n2-192.168.1.12:9878
dLegerSelfId=n0
listenPort=10911

节点 1

# broker-n1.conf
enableDLegerCommitLog=true
dLegerGroup=DefaultDledgerGroup
dLegerPeers=n0-192.168.1.10:9878;n1-192.168.1.11:9878;n2-192.168.1.12:9878
dLegerSelfId=n1
listenPort=10912

节点 2

# broker-n2.conf
enableDLegerCommitLog=true
dLegerGroup=DefaultDledgerGroup
dLegerPeers=n0-192.168.1.10:9878;n1-192.168.1.11:9878;n2-192.168.1.12:9878
dLegerSelfId=n2
listenPort=10913

四、部署实战

4.1 Docker 部署

# docker-compose.yml
version: '3'
services:
  nameserver:
    image: apache/rocketmq:5.0.0
    command: sh mqnamesrv
    ports:
      - "9876:9876"
  
  dledger-node0:
    image: apache/rocketmq:5.0.0
    command: sh mqbroker -n nameserver:9876 -c /opt/rocketmq/conf/broker-n0.conf
    ports:
      - "10911:10911"
      - "9878:9878"
    volumes:
      - ./broker-n0.conf:/opt/rocketmq/conf/broker-n0.conf
      - dledger-n0-data:/data/rocketmq/store
  
  dledger-node1:
    image: apache/rocketmq:5.0.0
    command: sh mqbroker -n nameserver:9876 -c /opt/rocketmq/conf/broker-n1.conf
    ports:
      - "10912:10912"
      - "9879:9878"
    volumes:
      - ./broker-n1.conf:/opt/rocketmq/conf/broker-n1.conf
      - dledger-n1-data:/data/rocketmq/store
  
  dledger-node2:
    image: apache/rocketmq:5.0.0
    command: sh mqbroker -n nameserver:9876 -c /opt/rocketmq/conf/broker-n2.conf
    ports:
      - "10913:10913"
      - "9880:9878"
    volumes:
      - ./broker-n2.conf:/opt/rocketmq/conf/broker-n2.conf
      - dledger-n2-data:/data/rocketmq/store

volumes:
  dledger-n0-data:
  dledger-n1-data:
  dledger-n2-data:

4.2 Kubernetes 部署

# statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: rocketmq-dledger
spec:
  serviceName: rocketmq-dledger
  replicas: 3
  selector:
    matchLabels:
      app: rocketmq-dledger
  template:
    metadata:
      labels:
        app: rocketmq-dledger
    spec:
      containers:
      - name: broker
        image: apache/rocketmq:5.0.0
        command: ["sh", "-c", "mqbroker -n rocketmq-nameserver:9876 -c /opt/rocketmq/conf/broker.conf"]
        ports:
        - containerPort: 10911
        - containerPort: 9878
        env:
        - name: DLedgerSelfId
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        volumeMounts:
        - name: config
          mountPath: /opt/rocketmq/conf
        - name: data
          mountPath: /data/rocketmq/store
  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes: ["ReadWriteOnce"]
      resources:
        requests:
          storage: 100Gi

五、故障切换

5.1 切换流程

graph TB
    A[Leader 宕机] --> B[Follower 检测]
    B --> C{超时?}
    C -->|是 | D[发起选举]
    C -->|否 | E[等待]
    D --> F[投票]
    F --> G{获得多数票?}
    G -->|是 | H[成为新 Leader]
    G -->|否 | I[选举失败]
    H --> J[恢复正常服务]

5.2 切换时间

切换时间分析:
- 故障检测:3-5 秒
- 选举过程:1-3 秒
- 总切换时间:5-10 秒

5.3 切换验证

#!/bin/bash
# DLedger 切换验证脚本

echo "=== DLedger 切换验证 ==="

# 1. 查看当前 Leader
echo -e "\n当前 Leader:"
mqadmin clusterList -n ns1:9876 | grep -i leader

# 2. 停止 Leader
echo -e "\n停止 Leader..."
ssh leader-node "systemctl stop rocketmq-broker"

# 3. 等待切换
echo -e "\n等待切换..."
sleep 10

# 4. 查看新 Leader
echo -e "\n新 Leader:"
mqadmin clusterList -n ns1:9876 | grep -i leader

# 5. 验证数据一致性
echo -e "\n验证数据一致性:"
echo "test" | mqadmin sendMessage -n ns1:9876 -t test-topic
mqadmin consumeMessage -n ns1:9876 -g test-consumer -t test-topic

echo -e "\n=== 验证完成 ==="

六、数据一致性

6.1 一致性保证

DLedger 一致性保证:
1. 多数派写入
2. 日志复制
3. Leader 线性化

6.2 写入流程

sequenceDiagram
    participant C as Client
    participant L as Leader
    participant F1 as Follower 1
    participant F2 as Follower 2
    
    C->>L: 写入请求
    L->>L: 追加日志
    L->>F1: 复制日志
    L->>F2: 复制日志
    F1-->>L: ACK
    F2-->>L: ACK
    L->>L: 提交(多数派确认)
    L-->>C: 返回成功

6.3 读取流程

sequenceDiagram
    participant C as Client
    participant L as Leader
    
    C->>L: 读取请求
    L->>L: 检查日志
    L-->>C: 返回数据

七、监控运维

7.1 监控指标

指标说明告警阈值
dledger_leader当前 Leader-
dledger_termRaft Term-
dledger_commit_log_size提交日志大小-
dledger_replication_lag复制延迟> 1000ms

7.2 运维命令

# 查看 DLedger 状态
mqadmin clusterList -n ns1:9876

# 查看 Raft 状态
# 需要访问 DLedger 接口
curl http://localhost:9878/raft/status

# 手动触发选举
# 停止当前 Leader,Follower 会自动选举

7.3 日志分析

#!/bin/bash
# DLedger 日志分析脚本

LOG_FILE="/var/log/rocketmq/dledger.log"

echo "=== Leader 变更统计 ==="
grep "changeLeader" $LOG_FILE | \
  awk '{print $1, $2, $3}' | \
  sort | uniq -c | sort -rn

echo -e "\n=== 选举统计 ==="
grep "election" $LOG_FILE | \
  awk '{print $1, $2, $3}' | \
  sort | uniq -c | sort -rn

echo -e "\n=== 最近 Leader 变更 ==="
grep "changeLeader" $LOG_FILE | tail -10

八、最佳实践

8.1 配置建议

DLedger 配置建议:
1. 节点数量:3 或 5(奇数)
2. 跨可用区部署
3. 独立磁盘
4. 监控 Raft 状态
5. 定期演练切换

8.2 性能优化

性能优化:
1. 使用 SSD 磁盘
2. 配置合理的批次大小
3. 优化网络配置
4. 监控复制延迟
5. 建立监控告警

8.3 检查清单

运维检查:
- [ ] DLedger 状态正常
- [ ] Leader 稳定
- [ ] 复制延迟正常
- [ ] 磁盘使用率正常
- [ ] 监控告警正常
- [ ] 定期切换演练

总结

RocketMQ DLedger 的核心要点:

  1. 架构演进:主从模式 → DLedger 模式
  2. Raft 协议:Leader 选举、日志复制
  3. 配置方法:Broker 配置、多节点配置
  4. 部署实战:Docker、Kubernetes
  5. 故障切换:自动切换、切换验证
  6. 数据一致性:多数派写入、日志复制

核心要点

参考资料


分享这篇文章到:

上一篇文章
Kafka KSQL 流式 SQL 实战指南
下一篇文章
AI 应用监控与告警体系