笔记:08_尚硅谷技术之ZookeeperV3.3.pdf
08_尚硅谷技术之Zookeeper(源码解析)V3.3.pdf
Zookeeper从入门到精通.xmind

是一个基于观察者模式设计的分布式服务管理框架

特点

1) Zookeeper:一个领导者(Leader) , 多个跟随者(Follower) 组成的集群。
2) 集群中只要有半数以上节点存活, Zookeeper集群就能正常服务。 所以Zookeeper适合安装奇数台服务器。
3) 全局数据一致:每个Server保存一份相同的数据副本, Client无论连接到哪个Server, 数据都是一致的。
4) 更新请求顺序执行, 来自同一个Client的更新请求按其发送顺序依次执行。
5) 数据更新原子性, 一次数据更新要么成功, 要么失败。
6) 实时性, 在一定时间范围内, Client能读到最新数据。

应用场景

统一命名服务、统一配置管理、统一集群管理、服务器节点动态上下线、软负载均衡
image.png

Zab协议

https://blog.csdn.net/liuchang19950703/article/details/111406622

Zab协议核心

Zab协议的核心:定义了事务请求的处理方式
1)所有的事务请求必须由一个全局唯一的服务器来协调处理,这样的服务器被叫做 Leader服务器。其他剩余的服务器则是 Follower服务器
2)Leader服务器 负责将一个客户端事务请求,转换成一个 事务Proposal,并将该 Proposal 分发给集群中所有的 Follower 服务器,也就是向所有 Follower 节点发送数据广播请求(或数据复制)
3)分发之后Leader服务器需要等待所有Follower服务器的反馈(Ack请求),在Zab协议中,只要超过半数的Follower服务器进行了正确的反馈后(也就是收到半数以上的Follower的Ack请求),那么 Leader 就会再次向所有的 Follower服务器发送 Commit 消息,要求其将上一个 事务proposal 进行提交。
ZooKeeper - 图2

Zookeeper工作原理

Zookeeper 的核心是原子广播,这个机制保证了各个 Server 之间的同步。实现这个机制的协议叫做 Zab 协议。Zab 协议有两种模式,它们分别是恢复模式(选主)广播模式(同步)。当服务启动或者在领导者崩溃后,Zab 就进入了恢复模式,当领导者被选举出来,且大多数 Server 完成了和 leader 的状态同步以后,恢复模式就结束了。状态同步保证了 leader 和 Server 具有相同的系统状态。

zookeeper 是如何保证事务的顺序一致性的?

两阶段提交保证最终一致性,
自增的事务id(zxid)保证顺序性
详细回答:zk数据写入是leader来协调的,通过两阶段提交来写入,第一阶段leader把写入事件作为提案广播给所有follower,可以写入的follower返回确认信息,第二阶段leader半数以上的ack信息确认写入可以生效,向所有follower广播commit将提案生效
zk有一个自增的事务id就是zxid,高位32位是记录leader的任期,地位32为是事务的计数器,所以同一任期的zxid是连续的,follower通过对比新提案的ZXID与自身最新ZXID是否相差“1”,来保证事务严格按照顺序生效的。

ZooKeeper选举机制

image.png

第一次启动

image.png

非第一次启动

image.png

选举机制总结

节点在一开始都处于选举节点,只要有一个节点得到超过半数节点的票数,它就可以当选准 Leader,只有到达第三个阶段(也就是同步阶段),这个准 Leader 才会成为真正的 Leader。
Zookeeper 规定所有有效的投票都必须在同一个 轮次 中,每个服务器在开始新一轮投票时,都会对自己维护的 logicalClock 进行自增操作
每个服务器在广播自己的选票前,会将自己的投票箱(recvset)清空。该投票箱记录了所受到的选票。
例如:Server_2 投票给 Server_3,Server_3 投票给 Server_1,则Server_1的投票箱为(2,3)、(3,1)、(1,1)。(每个服务器都会默认给自己投票)
前一个数字表示投票者,后一个数字表示被选举者。票箱中只会记录每一个投票者的最后一次投票记录,如果投票者更新自己的选票,则其他服务器收到该新选票后会在自己的票箱中更新该服务器的选票。
Fast Leader Election(快速选举)
前面提到的 FLE 会选举拥有最新Proposal history (lastZxid最大)的节点作为 Leader,这样就省去了发现最新提议的步骤。这是基于拥有最新提议的节点也拥有最新的提交记录

  • 成为 Leader 的条件:
    1)选 epoch 最大的
    2)若 epoch 相等,选 zxid 最大的
    3)若 epoch 和 zxid 相等,选择 server_id 最大的(zoo.cfg中的myid)

节点在选举开始时,都默认投票给自己,当接收其他节点的选票时,会根据上面的 Leader条件 判断并且更改自己的选票,然后重新发送选票给其他节点。当有一个节点的得票超过半数,该节点会设置自己的状态为 Leading ,其他节点会设置自己的状态为 Following

ZooKeeper分布式锁案例

什么叫做分布式锁呢?


比如说”进程 1”在使用该资源的时候,会先去获得锁, “进程 1”获得锁以后会对该资源 保持独占,这样其他进程就无法访问该资源, “进程 1”用完该资源以后就将锁释放掉,让其他进程来获得锁,那么通过这个锁机制,我们就能保证了分布式系统中多个进程能够有序的访问该临界资源。那么我们把这个分布式环境下的这个锁叫作分布式锁。
方式一:
image.png
得到锁:服务器1创建临时有序节点,判断是不是序号最小的临时有序节点
如果是得到锁
服务器2创建临时有序节点,判断是不是序号最小的临时有序节点,
如果不是,监听上一个节点
释放锁:删除节点
为什么用临时节点:如果不用临时节点服务器1挂掉,序号最小的节点没有被删除掉,服务器2就会拿不到锁,造成死锁


面试

image.png
image.png
image.png

1. zookeeper常用场景

zookeeper的分布式协调场景

image.png

zookeeper的分布式锁场景

方式二:
image.png
image.png
image.png
得到锁:服务器1创建一个临时节点,创建成功,得到锁
服务器2创建一个同名临时节点,如果不成功说明锁被占用,监听该节点
释放锁:删除节点

zookeeper配置信息管理

image.png

HA高可用(两台机器做主备)

image.png

2. 如何设计分布式锁

如果在一个分布式系统中,我们从数据库中读取一个数据,然后修改保存,这种情况很容易遇到并发问题。因为读取和更新保存不是一个原子操作,在并发时就会导致数据的不正确。这种场景其实并不少见,比如电商秒杀活动,库存数量的更新就会遇到。如果是单机应用,直接使用本地锁就可以避免。如果是分布式应用,本地锁派不上用场,这时就需要引入分布式锁来解决。
由此可见分布式锁的目的其实很简单,就是为了保证多台服务器在执行某一段代码时保证只有一台服务器执行
https://www.zhihu.com/question/300767410/answer/1749442787

image.png
image.png
image.png
image.png
NX,PX具体用法http://doc.redisfans.com/string/set.html

2.1 redis最普通的分布式锁的实现原理

image.png
image.png

为什么redis设置随机值?

流程:拿到redis锁->设置随机值->处理业务->释放锁(校验redis锁的值是不是当前服务器设置的随机值,如果是删掉,如果不是不允许删掉)
服务器1拿到锁并设置随机值1,但是处理业务的时间超过了30s,那么当前的redis锁将会过期,因为服务器2 每隔1s去请求锁,并拿到锁设置随机值2,此时服务器1处理完业务超过了30s,删除锁,如果不设置随机值服务器1就会把服务器2的锁删掉
image.png

缺点

如果redis是单例的,那么redis挂掉,那么分布式锁就将直接失效
如果redis是主从复制的架构,因为redis是异步同步数据的,在主节点上设置一把锁,主节点挂掉,从节点还没来得及同步,那么锁就丢失了,别的服务器就会拿到锁

2.2 RedLock算法(官方推荐)