Bully、Raft、ZAB 三大经典分布式选举算法

Bully、Raft、ZAB 三大经典分布式选举算法

1. Bully 算法

1.1 算法思想 👑

Bully算法是一种基于节点ID的选举算法,核心思想是让最高ID的节点成为领导者。当节点发现协调者失效时,会向所有更高ID节点发起挑战,若没有响应则宣布自己为领导者。

1.2 算法原理 ⚙️

节点检测到协调者失效
是否有更高ID节点?
向更高ID节点发送Election消息
宣布自己为领导者
收到应答?
等待更高ID节点宣布
广播Coordinator消息

1.3 流程图 📊

超时
收到应答
超时
节点启动
监控协调者
检测协调者失效
发起选举
向更高ID节点发送Election
等待应答
放弃选举
宣布自己为领导者
广播Coordinator

1.4 C++实现关键代码

class BullyNode {
public:
    BullyNode(int id, vector<int> peers) : node_id(id), peers(peers) {}
    
    void startElection() {
        bool higherNodeResponded = false;
        
        for (int peer : peers) {
            if (peer > node_id) {
                // 向更高ID节点发送选举消息
                if (sendElectionMessage(peer)) {
                    higherNodeResponded = true;
                }
            }
        }
        
        if (!higherNodeResponded) {
            becomeLeader();
        }
    }
    
    void becomeLeader() {
        is_leader = true;
        for (int peer : peers) {
            sendLeaderAnnouncement(peer);
        }
    }
    
private:
    int node_id;
    vector<int> peers;
    bool is_leader = false;
};

2. Raft 算法

2.1 算法思想 🚣

Raft通过任期(term)机制日志复制实现分布式一致性,将问题分解为领导者选举、日志复制和安全性三个子问题。

2.2 状态转换图 🔄

选举超时
获得多数票
发现更高任期
发现更高任期
任期结束
Follower
Candidate
Leader

2.3 选举流程 ⚡

CandidateFollower1Follower2RequestVote(term)RequestVote(term)VoteGrantedVoteGrantedAppendEntries(心跳)AppendEntries(心跳)CandidateFollower1Follower2

2.4 C++实现关键代码

class RaftNode {
public:
    enum State { FOLLOWER, CANDIDATE, LEADER };
    
    void startElection() {
        current_term++;
        state = CANDIDATE;
        votes_received = 1; // 投票给自己
        
        // 请求其他节点投票
        for (auto& peer : peers) {
            RequestVoteRequest req;
            req.term = current_term;
            req.candidate_id = node_id;
            req.last_log_index = log.last_index();
            req.last_log_term = log.last_term();
            
            sendRequestVote(peer, req);
        }
        
        // 设置选举超时
        startElectionTimer();
    }
    
    void handleVoteResponse(const VoteResponse& res) {
        if (res.term > current_term) {
            stepDown(res.term);
            return;
        }
        
        if (res.vote_granted) {
            votes_received++;
            if (votes_received > peers.size() / 2) {
                becomeLeader();
            }
        }
    }
    
    void becomeLeader() {
        state = LEADER;
        // 初始化nextIndex和matchIndex
        for (auto& peer : peers) {
            next_index[peer] = log.last_index() + 1;
            match_index[peer] = 0;
        }
        
        // 开始发送心跳
        startHeartbeat();
    }
};

3. ZAB 算法

3.1 算法思想 🐘

ZAB(ZooKeeper Atomic Broadcast)专为ZooKeeper设计,通过epoch机制两阶段提交确保消息顺序和一致性。

3.2 算法架构 🏗️

写请求
Proposal
Proposal
ACK
ACK
Commit
Commit
客户端
Leader
Follower1
Follower2

3.3 恢复流程 ♻️

崩溃恢复
多数派同意
发现更高ZXID
进入LOOKING状态
发现Leader失效
广播选举消息
收到选举响应
成为新Leader
接受新Leader
同步数据
开始广播

3.4 C++实现关键代码

class ZabNode {
public:
    void runLeaderElection() {
        current_epoch++;
        election_state = LOOKING;
        
        // 广播选举消息
        ElectionMessage msg;
        msg.epoch = current_epoch;
        msg.zxid = last_zxid;
        msg.sid = node_id;
        
        broadcast(msg);
        
        // 收集投票
        map<int, ElectionMessage> votes;
        while (votes.size() <= peers.size() / 2) {
            ElectionMessage response = waitForResponse();
            votes[response.sid] = response;
        }
        
        // 选择Leader(最高ZXID优先)
        int leader_id = selectLeader(votes);
        
        if (leader_id == node_id) {
            becomeLeader();
        } else {
            becomeFollower(leader_id);
        }
    }
    
    void broadcastTransaction(Transaction txn) {
        // 阶段1:广播提案
        Proposal prop;
        prop.zxid = next_zxid++;
        prop.txn = txn;
        
        for (auto& peer : followers) {
            sendProposal(peer, prop);
        }
        
        // 等待ACK
        int ack_count = 0;
        while (ack_count <= followers.size() / 2) {
            if (receiveAck()) ack_count++;
        }
        
        // 阶段2:广播提交
        CommitMessage commit;
        commit.zxid = prop.zxid;
        
        for (auto& peer : followers) {
            sendCommit(peer, commit);
        }
        
        // 本地提交
        applyTransaction(txn);
    }
};

4. 算法对比分析

4.1 特性对比表 📋

特性BullyRaftZAB
选举基础节点ID任期+日志Epoch+ZXID
消息复杂度O(n²)O(n)O(n)
领导者变更立即生效任期结束生效Epoch变更生效
数据一致性不保证强一致性顺序一致性
适用场景小规模集群通用分布式系统协调服务

4.2 适用场景分析 🔍

在这里插入图片描述

5. 实现注意事项

5.1 通用实现模式 🧩

«interface»
ElectionAlgorithm
+startElection()
+handleMessage()
+becomeLeader()
+becomeFollower()
BullyImpl
+startElection()
+handleElectionMessage()
RaftImpl
+startElection()
+handleVoteRequest()
ZABImpl
+runLeaderElection()
+handleElectionResponse()

5.2 关键挑战与解决方案 🛡️

挑战解决方案
网络分区超时机制+心跳检测
脑裂问题多数派(Quorum)决策机制
拜占庭故障数字签名+身份认证(非本文算法核心关注点)
日志一致性两阶段提交(2PC)+复制状态机
性能优化批量提交+流水线复制

6. 参考

  • 简单系统:选择Bully算法实现简单快速
  • 数据强一致:Raft提供完整解决方案
  • 协调服务:ZAB与ZooKeeper深度集成
  • 大规模集群:考虑Raft变种或Paxos家族
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值