技术

zookeeper源码学习-QuorumVerifier

This post is currently available in Chinese only. The original text follows.Open the Chinese page →

Quorum的验证器,Quorum是一种分布式的机制,用来定义在分布式系统中,某个请求是否能够被确认。

ZK默认的实现是QuorumMaj,也就是超过半数投票者的时候,认为投票通过

public interface QuorumVerifier {

    long getWeight(long id);       //权重
    boolean containsQuorum(Set<Long> set);  //是否实现了quorum机制
    long getVersion();  //版本
    void setVersion(long ver);
    Map<Long, QuorumServer> getAllMembers();     //获取所有节点
    Map<Long, QuorumServer> getVotingMembers();  //获取所有投票节点
    Map<Long, QuorumServer> getObservingMembers();
    boolean equals(Object o);
    String toString();

}

QuorumMaj

QuorumMaj是默认的QuorumVerifier的实现,里面会存储一个half来表示节点的一半

private Map<Long, QuorumServer> allMembers = new HashMap<Long, QuorumServer>();
    private Map<Long, QuorumServer> votingMembers = new HashMap<Long, QuorumServer>();
    private Map<Long, QuorumServer> observingMembers = new HashMap<Long, QuorumServer>();
    private long version = 0;
    private int half;     

在创建QuorumVerifier的时候,会传入一个节点列表,然后会根据其中的参与者的数量,确定出来投票节点的数量,进而得出half的值,如果是在启动中创建出来的,则会根据配置信息进行创建。

如果没有指定节点类型,则节点默认为参与者

public QuorumMaj(Map<Long, QuorumServer> allMembers) {
        this.allMembers = allMembers;
        for (QuorumServer qs : allMembers.values()) {
            if (qs.type == LearnerType.PARTICIPANT) {
                votingMembers.put(Long.valueOf(qs.id), qs);
            } else {
                observingMembers.put(Long.valueOf(qs.id), qs);
            }
        }
        half = votingMembers.size() / 2;
    }

public QuorumMaj(Properties props) throws ConfigException {
        for (Entry<Object, Object> entry : props.entrySet()) {
            String key = entry.getKey().toString();
            String value = entry.getValue().toString();

            if (key.startsWith("server.")) {
                int dot = key.indexOf('.');
                long sid = Long.parseLong(key.substring(dot + 1));
                QuorumServer qs = new QuorumServer(sid, value);
                allMembers.put(Long.valueOf(sid), qs);
                if (qs.type == LearnerType.PARTICIPANT) {
                    votingMembers.put(Long.valueOf(sid), qs);
                } else {
                    observingMembers.put(Long.valueOf(sid), qs);
                }
            } else if (key.equals("version")) {
                version = Long.parseLong(value, 16);
            }
        }
        half = votingMembers.size() / 2;
    }

containsQuorum 核心

用来判断给定的一个结合是否满足Quorum的要求,也就是说是否超过了半数。

public boolean containsQuorum(Set<Long> ackSet) {
        return (ackSet.size() > half);
    }