- 投票验证器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)台机器运行正常