(六)zookeeper的Leader选举与事务投票过半策略之QuorumMaj

  • 投票验证器QuorumVerifier
    投票验证器承担了事务投票、Leader选举等过程中是否保证过半的责任,接口结构如下:
public interface QuorumVerifier {
    long getWeight(long id);
    boolean containsQuorum(Set<Long> set);
    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

  • 成员变量
    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;

1.allMembers 表示此集群全部机器集合
2.votingMembers 表示此集群可投票机器集合,包含Leader和Follower
3.observingMembers 表示此集群观察者集合
4.version 表示该验证器的版本
5.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;
    }

解析如下:
1.参数为allMembers集合时,根据LearnerType判断是属于votingMembers集合还是属于observingMembers,half为 votingMembers.size() / 2
2.参数为解析配置文件后生成的Properties对象时,解析serverId和角色,存入相应的map

判断投票是否通过
    public boolean containsQuorum(Set<Long> ackSet) {
        return (ackSet.size() > half);
    }

只要发送ack的服务器数量大于一半就表示投票成功,使用这个投票验证器时,也正是验证了zookeeper服务器集群要想运行正常必须得保证(n/2 + 1)台机器运行正常

猜你喜欢

转载自blog.csdn.net/long9870/article/details/93737375
今日推荐