6.4Zookeeper 与分布一致性架构
问题:1.MySQL主主复制,应该选择哪个主服务器呢?主主复制,并不是两个主服务器同时对外提供写操作。在一段时间内,只有一个主服务器对外提供写操作服务。
====>哪个主服务器为当前活动的主服务器呢?
====>选择主服务器。
2.NoSql-HBase:HMaster可能有多个,但是只能有一个HMaster是活动的,对外提供服务。其他HMaster是备份的。
====>提高可用性:当主HMaster宕机时,其他HMaster服务器可以提供同样的写入操作。
====>哪个HMaster服务器是可以选择呢?
分布式系统中重要点:分布式一致性。 分布式一致性算法----产品Zookeeper。
1.分布式系统脑裂
在一个分布式系统中,不同服务器获得了相互冲突的数据信息或者执行命令,导致整个集群陷入混乱,数据损坏,被称作分布式系统脑裂。
2.数据库主主备份

解析:MySQL主主复制为例。 两个主服务器(两个Master实例),两个Master实例可以主主复制。
但是在一个时间段内,只有一个主服务器Master实例对外提供写服务。
====>如果两个主服务器都对外提供服务写服务,A修改数据1为X,B修改数据1为Y,
====>两主服务器相互同步时,造成数据损坏==>数据同步失败==>数据一致性遭到破坏
====>所以:为了避免数据遭到破坏,保证数据一致性。 一段时间内, 要么只有主服务器A对外提供服务(所有的请求都连接到主服务器A),向A写入,由A向B同步。 只有当主服务器A失效时,选择主服务器B对外提供服务,写入B服务器。等待主服务器A恢复,由B再向A同步。这样,主主复制同步时,数据可以保证是一致的。
====>一段时间内,有且只有一个主服务器对外提供服务。
问题:哪个服务器应当作为当前的主活动服务器呢?
假如:一部分客户端认为A是主服务器,向A写入;一部分认为B是主服务器,向B写入
====>相互同步造成数据冲突
====>所以要有专门的服务器提供主服务器的判断和选择。比如;zookeeper服务器。
高可用性:两台主服务器,失效时,是可以相互接替,对外提供服务。 专门应用(比如Zookeeper),提供判断和选择主服务器,这个应用本身应该部署几台服务器呢?如果部署一台,当zookeeper宕机时,依然不知道那台服务器是主服务器。====>选择主服务器的应用本身,也需要高可用。
高可用策略:应用部署到多个服务器上,任何一个服务器宕机,都不会影响系统提供服务。比如:zookeeper部署多台服务器。
但是,Zookeeper本身如何保证一致性呢?zookeeper集群内服务器之间数据一致性呢?,
比如:专有应用zookeeper,部署两个服务器(zookeeper1,zookeeper2)。
主节点A向zookeeper1申请成为当前活动节点,主节点B向zookeeper2申请成为当前活动节点。
到底哪个才能成为主节点呢?A?B?zookeeper1和zookeeper2如何保证数据一致呢?
分布式系统的难点: 如何保证分布式系统高可用的情况下,有多台服务器,这些服务器又不是保持数据状态一致的。
解决方案:zookeeper。分布式一致性的应用服务。如何实现数据一致性呢?如何保证数据是统一的呢?
3.分布式一致性算法Paxos
对外提供统一的决策,或者说是统一的数据状态。

Proposer:申请者,提案者。
Acceptors: 接受者。
Learner: 学习者,获取最终的决策结果。获取最终的数据i一致性。

解析:如果经过投票,已经决定让A成为主服务器。Learner已经得到决策结果:让A成为主服务器。
如果B再次申请成为主服务器,提案就会被驳回。B的申请就会被拒绝。最终仍然是A为主服务器。
访问:其他客户端询问Learner当前的主服务器。Learner返回A。所有客户端都统一得到A是主服务器。
Acceptor高可用:其中一台Acceptor服务器宕机,其他Acceptors通过投票仍然能选择出最终结果。通过投票来决定最终的一致性。这个一致性结果在集群中是统一的。
分布式一致性算法:既保证了高可用,由保证了最终一致性。
生产环境中:Paxos比较复杂,不常用。
投票选举过程:
第一阶段:Prepare阶段。Proposer向Acceptors 发出Prepare请求,Acceptors针对收到的Prepare请求进行Promise承诺。
第二阶段:Accept阶段。Proposer收到多数Acceptors承诺的Promise后,向Acceptors发出Propose请求,Acceptors针对收到的Promise请求进行Accept处理。
第三阶段:Learn阶段。Proposer在收到多数Acceptors的Accept之后,标志着本次Accept成功,决议形成,将形成的决议发送给所有的Learners。
4.Zab协议
核心点:通过投票,达到一致性。

1.请求提交: Request发送请求给LEADER,
2.发起提案:由LEADER发起提案,转交给FOLLOWER。
3.FOLLOWER投票:FOLLOWER自己决定提案能不能被接受。如果能接受,发送ACK进行确认。
4.LEADER提交提案:LEADER收到所有ACK确认后,提交提案给FOLLOWER。
5.FOLLOWER更新:达到最终一致性。
6.请他请求连接到FOLLOWER,可得到最终一致性的结果。


5.ZooKeeper的树状记录结构
/
|---------services
| |---------YaView
| |-----------servers
| | |----------stupidname
| | |----------morestupdity
| |
| |------------Locks
| |----------read-1
|
|---------apps
|---------users
6.ZooKeeper的API
String create(path,data,acl,flags);
void delete(path,expectedVersion);
Stat setData(path,data,expectedVersion);
(data,Stat) getData(path,watch);
Stat exists(path,watch);
String[] getChildren(path,watch);
void sync(path);
List multi(ops);
7.ZooKeeper的配置管理
配置管理:配置管理应用既要保证高可用,又要保证数据一致性。
/config
|-----------param1
|-----------param2
|-----------param3
Administrator(管理控制台): setData("/config/param1","value",-1);
Consumer(应用程序): getData("/config/param1",true);
8.ZooKeeper投票选举Master
/Servers
|---------s1
|---------s2
|---------leader
|----------constains 's1'
应用场景:
1.MySQL主主复制,选举主服务器----zookeeper选举。
2.或者当前主服务器A宕机,选举主服务器B成为当前的活动主服务器--zookeeper重新选举,抢占。
3. Hbase架构中选举HMaster-------- zookeeper选举
server1,server2竞选成为主服务器
getData("/servers/leader",true);----------------------------------------------server1,server2查看leader的选举结果。并监视路径:/servers/leader的变化
if successful follow the leader described in the data and exit---------------如果有返回值为A,当前已经有活动的主服务器,server1,server2竞选失败。
create("/server/leader",hostname,EPHEMERAL)-----------------------------如果没有返回值,说明还没有服务器成为当前活动的主服务器。server1,server2可以参加竞选器,FOLLOWER选举排队。创建路径:/servers/leader,并将自己的值写入。
if successful lead and exit
goto step 1
9.ZooKeeper投票选举Master(Python伪代码)
handle=zookeeper.init("localhost:2181",my_connection_watcher,10000,0);
(data,stat)=zookeeper.get(handle,"app/leader",true);
if(stat==None){
path=zookeeper.create(handle,"app/leader",hostname:info,[ZOO_OPEN_ACL_UNSAFE],zookeeper.EPHEMERAL);
if(path===None){
(data,stat)=zookeeper.get(handle,"app/leader",true);
#someone else is leader
#parse the string path that contains the leader address
}else{
#we are the leader continue leading
}
}else{
#someone else is the leader
#parse the string path that contains the leader address
}
快速提供主主切换。
10.集群管理(负载均衡与失效转移)
/nodes
|--------------------------node1
|--------------------------node2
|--------------------------node3
Monitoring process:
1.Watch on /nodes
2.On watch trigger do getChildren(/nodes,true)-------监控nodes节点
3.Track which nodes have gone away------------------失效删除--通知负载均衡服务器,不再给node节点发送请求。
Each Node:
1.Create /nodes/node-${i} as ephemeral nodes
2.keep updating /nodes/node-${i} periodically for node status change (status updates could be load/iostat/cpu/others)
评论