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)
评论