分布式、一致性、zookeeper

本文深入探讨Zookeeper在分布式数据存储一致性中的作用,包括ZAB协议、崩溃恢复模式、消息广播模式、选举算法以及Zookeeper在分布式协调、任务分配和避免脑裂等方面的应用。此外,还提到了Paxos算法、2PC协议和一致性哈希在分布式一致性中的角色。
摘要由CSDN通过智能技术生成

 

如何实现分布式数据存储一致

ZAB协议

主要特征:

崩溃恢复模式

消息广播模式

如何利用zookeeper进行选举,画图说明

master 选举-为其他集群机器服务

leader选举-集群启动时期、运行时期

为什么会存在zookeeper,它可以用在哪里

zookeeper 任务分配(以分布式日志收集任务为例)

ZAB如何避免写入阻塞(写锁,排他锁,分布式队列——FIFO,Barrier)

Zookeeper 避免脑裂

简述zookeeper部署的时候以多少个实例部署,为什么?

Zookeeper可以做横向扩展吗?可以通过增加机器可以增加集群的性能吗?

一致性hash 大数据日知录p15

简述paxos算法

paxos算法的应用

2PC

2pc何时出问题

如何实现分布式数据存储一致

有哪些一致性协议

ZAB协议、paxos协议、一致性哈希、两阶段提交协议2PC,3PC, raft

理论支撑:BASE = 基本可用,软状态,最终一致性

一致性模型分类

副本更新策略:同时更新,主从式更新,任意节点更新

~

zk如何保证数据一致性

具有原子性

sysc主动同步数据

 

ZAB协议

ZAB协议是为 分布式协调服务zk设计的 支持崩溃恢复的原子消息广播协议

主备模式:zk使用单一的主进程(leader)接受处理 客户端的事务请求,并采用ZAB(原子广播)协议,将服务器的数据变更以事务提议(proposal)的形式,广播到副本进程(follower)

主要特征:

  • 同一个时刻集群只有一个主服务器来广播服务器的状态变更
  • 保证全局的状态(数据)变更序列被顺序处理(zxid)
  • leader出错时,崩溃恢复,容错,高可用

(提交的,就被所有提交;没提交的,就丢弃)

  • 确保在leader提交的事务,最终也要被所有服务器提交(leader down时)
  • 确保丢弃只在leader被提出但未被提交的事务

 

实现方式:两种基本模式(情况)----崩溃恢复模式、消息广播模式

崩溃恢复模式

  • 启动:当zk集群在刚启动,或者leader失去过半follower,或者leader down机,ZAB就会进入“恢复模式”,选举产生新的leader服务器
  • 退出:当选举产生了leader,集群中已经有过半服务器与该服务器完成了状态(数据)同步,ZAB退出恢复模式
  • 目标: 提交的,就被所有提交;没提交的,就丢弃
    • 确保在leader提交的事务,最终也要被所有服务器提交
    • 确保丢弃只在leader被提出但未被提交的事务
  • 实现方式:只要保证选举出来的leader拥有集群中所有机器最高编号的事务提议(zxid最大)
  • 数据同步方式:选举完leader后
    • 检查事务日志
    • 为每个follower分配队列,将没有被同步的(数据+commit)逐个发送给follower
    • 同步完成后再将其加入正常的follower列表
  • 丢弃未被提交的事务
    • zxid的格式:低32位是事务的单调递增计数器,高32位代表leader周期--epoch编号
    • 当选举出最大的zxid时,解析出epoch值,+1后应用到新leader上
    • 当拥有旧epoch值的服务器加入和启动时,则无法成为leader,且未被提交的旧事务会被要求去除

 

消息广播模式

具体过程

  • leader会为事务提议分配全局单调递增的唯一id——事务ID(zxid),来保证事务按序处理
  • leader为每一个follower分配一个队列,将事务提议放入队列中
  • follower接收事务提议后,先持久化到 事务日志,成功后反馈一个ack响应
  • 当leader接收到过半的响应后,广播commit消息,通知follower提交事务

特点:

  • 所有follower要么正常反馈事务提议,要么抛弃leader;如果此时leader down,进入崩溃恢复模式
  • 基于FIFO特性的TCP协议进行网络通信,保证广播过程中消息 接收与发送的 顺序性
  • 退出恢复模式后,进入消息广播模式,此时集群有leader且过半服务器数据同步
  • 当加入新服务器follower,会进入数据恢复模式:主动找到leader,同步数据

如何利用zookeeper进行选举,画图说明

master的作用

  • 读写分离时,写请求主要由master处理
  • 负责处理一些复杂逻辑,同步到集群的其他系统中
  • yarn中管理资源,负载均衡

master 选举-为其他集群机器服务 利用其在高并发情况下zk节点创建的全局唯一性

  • zookeeper的节点有两种类型,持久节点和临时节点
  • 集群节点竞争会在zk的node下注册一个临时节点,命名为/znode/str
  • 成功注册的节点会成为master
  • 其他集群节点在znode上注册一个子节点变更的watcher,观察master是否存活
  • master挂掉后,临时节点会被自动删除,
  • 其他节点通过watcher收到通知,会重新竞争注册该临时节点,注册成功的节点重新成为master

leader选举-集群启动时期、运行时期

数据格式

(服务器id,事务zxid,当前服务器选举轮次electionEpoch,被选举服务器的选举轮次peerEpoch,服务器状态state)

默认的选举策略:fastleaderelection

集群启动时期:3台服务器为例,挂掉一台,还剩两台参与选举

  1. 至少是2台,建议3台,每台机器有不同的myid,有事务提议的zxid(启动时是zxid = 0)
  2. 每台机器会发出一个投票,格式(myid,zxid,...),假设两台服务器,分别投了是s1:(1,0,...)、s2:(2,0,...)
  3. 接收各个服务器的投票,判断投票的有效性:是否本轮投票、是否来自looking状态服务器:(通过比较两个选举轮次,投票携带的state是否是looking)
  4. 统计投票1(PK)
    1. 优先检查ZXID,ZXID比较大的服务器优先作为leader
    2. 如果zxid相同,则比较myid,myid比较大的作为leader
    3. s1发现zxid相同,myid s2>s1,则将自己的投票改掉(1,0,...) -> (2,0,...)
    4. s2不变,仍旧是 (2,0,...)
  5. 统计投票2
    1. 集群有过半的服务器接收到相同的投票信息(2,0),则leader选举成功(2台的过半就是2台)
  6. 改变服务器状态
    1. 每个服务器根据投票信息,改变自己为leader或者follower,开始执行功能(数据同步,消息广播)

运行时期 :3台服务器为例, 挂掉一台,还剩两台参与选举 zxid != 0

  1. 变更状态:leader dwon后,余下的非observer服务器会将自己服务器状态变更为LOOKING,开始进入选举流程
  2. 发起投票:投票信息(myid,zxid,...),第一轮都投给自己:s1(1, 123,...) s3(3, 122,...)
  3. 接收投票,验证有效性
  4. 统计投票1:由于s1.zxid > s3.zxid,s3将投票信息改为s3(1, 123,...)
  5. 统计投票2:过半服务器收到(1, 123,...),s1被选举为leader
  6. 变更状态

 

 

为什么会存在zookeeper,它可以用在哪里

zk是开源的分布式协调服务,是google chubby[tʃʌbi]的开源实现

设计目标:将复杂和易错的分布式一致性服务封装,提供分布式协调服务,高可用服务,具有严格顺序访问控制能力

应用场景:数据发布与订阅,负载均衡,命名服务,分布式协调/通知,集群管理,master选举,分布式锁,分布式队列,商品购买的顺序性

特点1:

简单的数据类型 znode,全量数据存储在内存中

顺序访问 全局递增编号zxid

高性能,尤其是读

幂等性:反复执行同一个操作与只正确执行一次操作效果相同;对系统来讲,同一操作反复调用其状态不变

可构建集群,集群间 TCP连接

特点2:A I D

I顺序一致性,事务请求按顺序处理

A原子性,要么所有节点成功处理了某事务,要么全部没有(保证了数据的一致性)

单一视图:无论连接着哪个节点,客户端看到的服务端数据类型全部一样

D可靠(持久)性:一旦成功处理了某事务。其对服务端状态的更改是永久的

伪实时性:保证一定时间段内,客户端最终能读到最新的数据

zookeeper 任务分配(以分布式日志收集任务为例)

作用:任务自动负载均衡,汇报任务负载情况,高可用

  1. 注册收集器机器:在zk下创建根节点/logs/collector,每个收集器启动时创建 持久节点 /logs/collector/[hostname] (内部存有任务列表、状态信息等数据,不能用临时节点)
  2. 日志源机器任务分发:将日志源机器分成若干组,将分组后的机器列表写到收集器的子节点内,如 /logs/collector/host1
  3. 状态汇报:考虑到收集器会挂掉,收集器会在hostname节点下创建状态子节点status( /logs/collector/host1/status),收集器需定期向status写入日志收集进度
    1. 当作心跳检测,日志心跳根据其最后更新时间判断收集器是否存活
    2. 日志系统主动轮询收集status,节省网卡流量;不用watcher,因为status更新太频繁
    3. 可以在status中同时汇报任务负载情况,以便任务局部动态分配
  4. 动态分配:若收集器机器挂掉或者扩容,则需要要动态分配
    1. 全局动态分配:对所有任务机器重新分组
    2. 局部动态分配:每个收集器在汇报日志收集status时,同时汇报任务负载情况;
      1. 如果机器挂了,将任务分配到其他负载较低的机器上去
      2. 如果加入新机器,从负载较高的机器上转移部分任务加入新机器

 

ZAB如何避免写入阻塞(写锁,排他锁,分布式锁、队列——FIFO,Barrier)

  • 排他锁 = 写锁 共享锁 = 读锁
  • 阻塞调用是指调用结果返回之前,当前线程会被挂起。函数只有在得到结果之后才会返回

 

分布式锁实现方式:

  1. 获取锁:竞争创建唯一临时子节点 /w/lock,未成功的客户端在 /w 注册一个子节点变更watcher监听
  2. 释放锁:写任务完成或节点挂掉,其他节点继续竞争写锁

以上方式容易造成羊群效应

 

  • 确定读写顺序,避免羊群效应:客户端收到过多和自己不想关的事件通知

 

  • 在zookeeper指定节点(lock)下创建临时顺序节点node_n
  • 获取lock下所有子节点children
  • 对子节点按节点自增序号从小到大排序
    • 读请求,向比自己序号小的最后一个 写 请求注册监听
    • 写请求,向序号小的上一个节点注册监听

 

基于ZooKeeper分布式锁的流程

  • 判断本节点是不是第一个子节点,若是,则获取锁;若不是,则监听比该节点小的那个节点的删除事件
  • 若监听事件生效,则回到第二步重新进行判断,直到获取到锁

 

 

 

Zookeeper 避免脑裂

Split-Brain:集群由于网络故障,分成了多个独立部分,多个master,相互之间不知道对方存活

 

zk集群 leader脑裂

ZooKeeper集群中必须超过半数节点(Majority)可用,整个集群才能对外可用

其他集群 master 脑裂 master假死造成

原因:单机“假死”:由于网络闪断,或是其自身由于负载过高(GC占用时间,CPU负载),无法及时对外响应

分布式脑裂:RM1假死后,RM2成为Active,此时RM1回恢复正常,则出现了分布式脑裂

Fencing机制:YARN引入fencing机制,借助zk数据节点的ACL权限控制实现不同RM的隔离,即创建的根节点必须携带ACL信息,以独占根节点。

过程:RM1恢复之后,会试图去更新*zk的相关数据,但发现没有权限,则自动切换为Standby

 

简述zookeeper部署的时候以多少个实例部署,为什么?

奇数台部署,zk选举时,只要半数拥护的机器就会成为leader,偶数台在容灾能力上没有优势(3,4台都只能挂1台)

Zookeeper可以做横向扩展吗?可以通过增加机器可以增加集群的性能吗?

可以设置多台observer,不参与投票(事务、leader选举),只负责读和事务转移

leader向observer发送INFORM(通知)——已被Commit的proposal

  • 不伤害写性能的情况下提供ZooKeeper的可扩展性,对读请求进行扩展
  • 另一个原因是跨数据中心部署时,优势是为本地读请求提供快速响应
    • 把Leader和Follower分散到多个数据中心的话,由于数据中心之间的网络的延迟,会导致集群性能的大幅度下降
    • 所以Leader和Follower部署在单独的数据中心,更新操作会在同一个数据中心来处理
    • 并将数据发送的其它数据中心的Observer,为本地读请求提供快速响应

A(原子性,全部执行或放弃)C(一致性,完整性)I(事务独立,序列化)D(持久性,更新永久) 关系数据库采纳的规则

BASE 基本可用(允许偶尔失败) 软状态(不要求任意时刻保持同步)最终一致性(一定时间窗口内一致)

原则:全局BASE,局部ACID == 新的CAP

一致性hash 大数据日知录p15

  • 一致性哈希算法在1997年由麻省理工学院的Karger等人在解决分布式Cache中提出的,设计目标是为了解决因特网中的热点(Hot spot)问题,初衷和CARP十分类似。一致性哈希修正了CARP使用的简单哈希算法带来的问题,使得DHT(分布式哈希表)可以在P2P环境中真正得到应用
  • DHT(分布式哈希表)是一种分布式存储方法。在不需要中心管理节点的情况下,每个客户端Ni负责存储落在一段哈希空间内的数据
  • 一致性哈希将整个哈希值空间组织成一个虚拟的圆环,机器可以根据IP和端口号经Hash映射到哈希值空间

最简单的原理:将数据key使用相同的函数Hash计算出哈希值,并确定此数据在环上的位置,从此位置沿环顺时针“行走”,第一台遇到的服务器就是其应该定位到的服务器。根据一致性哈希算法,数据A会被定为到Node A上,B被定为到Node B上,C被定为到Node C上,D被定为到Node D上

 

使用一致性哈希的好处在于,增减集群的缓存服务器时,只有少量的缓存会失效,回源量较小。

 

假设哈希空间长度(bit位) = 5,表达的数值范围是0-31,大圆表示机器节点(Ni),这台节点负责主键哈希值落在一定范围内的数据,H(key) = j

 

1.路由算法:如何根据数据key及哈希函数H定位记录内容

方法一,根据 j 遍历所有机器节点,找到Nx ,x >= j ; 效率太低

方法二,配置路由表,存储m条路由信息,第 i 项表示距离当前节点 2^i 哈希空间数值所在的机器节点

N14的路由表为: 假设 j = 18,18-14 = 4 ,根据路由表直接可找到数据在 N20

距离 1 2 4 8 16

机器节点 N20 N20 N20 N25 N5

 

路由算法: 类似于二分查找,代查距离不会原距离的超过一半(距离间都是*2的)

输入:向 Ni 发送初始查询请求,查询主键为key,H(key) = j = 27

输出:Ni 给出value,或返回不存在

算法:

1.Ni 检查是否在后继节点上: i < j <s,若是,则返回 (递归)

2.否则,查找路由表,找到小于 j 的最大编号 Nh (N25)(14+8 < 27 < 14+16)

3.Ni请求 Nh 代查,重复步骤1,2(递归)

虚拟节点 数据倾斜问题

同时数据定位算法不变,只是多了一步虚拟节点到实际节点的映射,例如定位到“Node A#1”、“Node A#2”、“Node A#3”三个虚拟节点的数据均定位到Node A上。这样就解决了服务节点少时数据倾斜的问题。在实际应用中,通常将虚拟节点数设置为32甚至更大,因此即使很少的服务节点也能做到相对均匀的数据分布

 

2.加入新节点

先通过路由算法查询H(Nnew) = new, 找到Nnew的后继节点Ns,Ns前继节点Np

改变三个节点的前继,后继节点记录

数据重新分片和分布,即将Ns节点存储的数据,按照架构迁移到Nnew

并发环境下一次性加入多个新节点时

将Nnew后继节点指向Ns,前继节点置 null

稳定性检测:P2P网络中每个节点定期执行

稳定性检测算法:略

 

3.节点离开:

正常:通知相应节点更改前后继节点,数据迁移至后继节点

异常:同一份数据备份副本 zk

 

特点:

一致性hash算法思路是将整个哈希值空间组织成一个虚拟的圆环,并通过hash算法加入对应服务节点(通过ip计算hash)组成服务节点圆环。(假设有我们要做5个物理节点,每个节点做5个虚拟节点,通过hash算法将物理节点的ip+虚拟节点标识,将转换成25个hash值,这些值就是服务节点在虚拟圆环的对应位置。)

  • 加入key时,先计算key的hash值,然后按顺时针方向,找最接近这个hash值得服务节点,并将key放入该服务节点;
  • 删除服务节点时,将该服务节点的key,按顺时针方向查找最近的服务节点,并将key放入该服务节点;
  • 添加服务节点时,通过hash算法计算对应的hash坐标,并按顺时针方向找到最近的服务节点,迭代该节点元素,将hash值小于等于新增服务节点的元素进行重新定位,定位至新增服务节点;

 

附录: 

良好的一致性hash算法,需要满足一下几点要求:平衡性(Balance)、单调性(Monotonicity)、分散性(Spread)、负载(Load)、平滑性(Smoothness)

平衡性(Balance) 

平衡性是指哈希的结果能够尽可能分布到所有的缓冲中去,这样可以使得所有的缓冲空间都得到利用。很多哈希算法都能够满足这一条件。

单调性(Monotonicity) 

单调性是指如果已经有一些内容通过哈希分派到了相应的缓冲中,又有新的缓冲区加入到系统中,那么哈希的结果应能够保证原有已分配的内容可以被映射到新的缓冲区中去,而不会被映射到旧的缓冲集合中的其他缓冲区。简单的哈希算法往往不能满足单调性的要求,如最简单的线性哈希:x = (ax + b) mod (P),在上式中,P表示全部缓冲的大小。不难看出,当缓冲大小发生变化时(从P1到P2),原来所有的哈希结果均会发生变化,从而不满足单调性的要求。哈希结果的变化意味着当缓冲空间发生变化时,所有的映射关系需要在系统内全部更新。而在P2P系统内,缓冲的变化等价于Peer加入或退出系统,这一情况在P2P系统中会频繁发生,因此会带来极大计算和传输负荷。单调性就是要求哈希算法能够应对这种情况。

分散性(Spread) 

在分布式环境中,终端有可能看不到所有的缓冲,而是只能看到其中的一部分。当终端希望通过哈希过程将内容映射到缓冲上时,由于不同终端所见的缓冲范围有可能不同,从而导致哈希的结果不一致,最终的结果是相同的内容被不同的终端映射到不同的缓冲区中。这种情况显然是应该避免的,因为它导致相同内容被存储到不同缓冲中去,降低了系统存储的效率。分散性的定义就是上述情况发生的严重程度。好的哈希算法应能够尽量避免不一致的情况发生,也就是尽量降低分散性。

负载(Load) 

负载问题实际上是从另一个角度看待分散性问题。既然不同的终端可能将相同的内容映射到不同的缓冲区中,那么对于一个特定的缓冲区而言,也可能被不同的用户映射为不同的内容。与分散性一样,这种情况也是应当避免的,因此好的哈希算法应能够尽量降低缓冲的负荷。

平滑性(Smoothness) 

平滑性是指缓存服务器的数目平滑改变和缓存对象的平滑改变是一致的。

简述paxos算法

paxos算法的应用

 

2PC

作用:保证在分布式事务中,要么所有进程都提交事务,要么都取消事务,即实现 原子性

唯一的 协调者、多个 参与者

表决阶段:协调者 向所有参与者 发送 vote-request,参与者回复 vote-commit or vote-abort

提交阶段:协调者搜集参与者的表决信息

若全部收到comit,则发送global-commit, 参与者全部提交事务

若有一个是abort,则发送global-abort, 参与者全部取消事务

存在3个阻塞状态:协调者wait(request之后),参与者init(等待request),ready(收到request)

引入超时判断机制和参与者互询机制

协调者wait,超时后发送global-abort

参与者init,超时后中止本地事务,发送vote-abort

参与者ready,询问另外的参与者Q,若Q是COMMIT,则COMMIT;abort,init -> abort

 

2pc何时出问题:若Q是ready,则询问其他参与者,若其他参与者都处于ready状态,这是2PC无法解决的,所有参与者进入阻塞

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值