JAVA:深入理解 ZAB 算法的技术指南

admin
6
2025-08-22

1、简述

在分布式系统中,一致性 是最重要的问题之一。ZooKeeper 作为分布式协调服务,其核心是通过 ZAB(ZooKeeper Atomic Broadcast)协议 来实现数据一致性。

ZAB 是 ZooKeeper 专门设计的一种 原子广播协议,类似于 Paxos,但更贴合 主从同步和崩溃恢复场景

image-ye6l.png


2、ZAB 算法

2.1 核心目标

ZAB 的设计目标是保证:

🔹 顺序一致性:所有事务请求(写操作)在所有节点上按相同顺序应用。

🔹 原子性:事务要么在所有节点上提交,要么不提交。

🔹 可恢复性:即使 Leader 宕机,系统仍能恢复并继续提供一致的服务。

2.2 ZAB 的工作流程

ZAB 协议有两个核心模式:

崩溃恢复(Crash Recovery)

🔹 Leader 崩溃后,集群进入恢复模式;

🔹 重新选举新的 Leader,并通过 同步阶段 确保新 Leader 与过半 Follower 数据一致。

消息广播(Message Broadcast)

🔹 在稳定状态下,Leader 接收客户端写请求;

🔹 Leader 将请求转为事务 Proposal,并发送给 Follower;

🔹 Follower 写入事务日志并返回 ACK;

🔹 当超过半数节点 ACK,Leader 提交事务并通知所有节点应用。

2.3 ZAB 与 Paxos 的区别

🔹 Paxos 更通用,解决分布式一致性问题;

🔹 ZAB 针对 ZooKeeper 进行了优化:

提供 **崩溃恢复 + 广播** 两阶段机制;
强调事务的顺序广播;
使用单 Leader 简化协议。

2.4 ZAB 协议的关键特性

崩溃恢复保障

通过选举和数据同步,保证新 Leader 一定包含所有已提交事务。

广播保障

🔹 提案必须经过半数以上确认;

🔹 Leader 负责保证顺序一致性。

数据同步策略

🔹 Leader 向 Follower 下发最新 Proposal;

🔹 Follower 回放事务日志,保证状态一致。

image-aarb.png


3、实践样例

虽然 ZAB 在 ZooKeeper 内部实现,我们无法直接“调用 ZAB”,但可以写一个 Java Demo 来模拟 主从事务提交

3.1. 定义事务 Proposal

class Proposal {
    private final String data;
    private final long zxid; // ZooKeeper事务ID

    public Proposal(long zxid, String data) {
        this.zxid = zxid;
        this.data = data;
    }

    public long getZxid() { return zxid; }
    public String getData() { return data; }
}

3.2 模拟 Leader

import java.util.*;
import java.util.concurrent.atomic.AtomicLong;

class Leader {
    private final List<Follower> followers;
    private final AtomicLong zxid = new AtomicLong(0);

    public Leader(List<Follower> followers) {
        this.followers = followers;
    }

    public void broadcast(String data) {
        long newZxid = zxid.incrementAndGet();
        Proposal proposal = new Proposal(newZxid, data);

        // 发送提案给所有Follower
        int ackCount = 1; // Leader 自己默认 ACK
        for (Follower f : followers) {
            if (f.receiveProposal(proposal)) {
                ackCount++;
            }
        }

        // 半数以上确认才提交
        if (ackCount > (followers.size() + 1) / 2) {
            commit(proposal);
        } else {
            System.out.println("Proposal " + newZxid + " commit failed.");
        }
    }

    private void commit(Proposal proposal) {
        System.out.println("Leader commit: " + proposal.getData());
        for (Follower f : followers) {
            f.commit(proposal);
        }
    }
}

3.3 模拟 Follower

import java.util.*;

class Follower {
    private final List<Proposal> log = new ArrayList<>();

    // 接收 Proposal 并写日志
    public boolean receiveProposal(Proposal proposal) {
        log.add(proposal);
        System.out.println("Follower received proposal: " + proposal.getData());
        return true; // 模拟成功ACK
    }

    // Leader 提交后应用事务
    public void commit(Proposal proposal) {
        System.out.println("Follower commit: " + proposal.getData());
    }
}

3.4 测试 Demo

public class ZABDemo {
    public static void main(String[] args) {
        List<Follower> followers = Arrays.asList(new Follower(), new Follower(), new Follower());
        Leader leader = new Leader(followers);

        leader.broadcast("Order-Create: #1001");
        leader.broadcast("Order-Pay: #1001");
        leader.broadcast("Order-Ship: #1001");
    }
}

运行结果示例

Follower received proposal: Order-Create: #1001
Follower received proposal: Order-Create: #1001
Follower received proposal: Order-Create: #1001
Leader commit: Order-Create: #1001
Follower commit: Order-Create: #1001
Follower commit: Order-Create: #1001
Follower commit: Order-Create: #1001
...

可以看到,Leader 发起提案,Follower 写日志并 ACK,超过半数后事务被提交。


4、应用场景

ZAB 算法在 ZooKeeper 中是核心协议,广泛用于:

🔹 分布式协调(服务注册、分布式锁)

🔹 元数据存储(Kafka、Hadoop 依赖 ZooKeeper)

🔹 选主机制(如 ElasticSearch Master 选举)


5、总结

🔹 ZAB 是 ZooKeeper 专属一致性协议,实现了原子广播;

🔹 与 Paxos 相比,ZAB 更关注 主从复制与事务顺序

🔹 通过 崩溃恢复 + 消息广播 两种模式,确保数据一致性;

🔹 在分布式系统中,它是保证一致性的重要基础。

动物装饰