国外简洁的网站,跨境电商服务平台有哪些,流程网站,济南网站建设公司哪家好分布式锁
分布式锁是控制分布式系统之间同步访问资源的一种方式#xff0c;如果不同系统是同一个系统的不同主机之间共享一个或一组资源#xff0c;那么访问这些资源的时候#xff0c;往往需要通过一些呼哧手段来防止彼此之间的干扰保证统一性#xff0c;因此需要分布式锁…分布式锁
分布式锁是控制分布式系统之间同步访问资源的一种方式如果不同系统是同一个系统的不同主机之间共享一个或一组资源那么访问这些资源的时候往往需要通过一些呼哧手段来防止彼此之间的干扰保证统一性因此需要分布式锁。
排他锁
简称X锁或写锁独占锁是一种基本的锁类型如果事务T1对数据对象Q1加上排他锁那么整个加锁期间只允许事务T1对Q1进行读写操作其他任何事务不能对Q1操作直到T1释放
定义锁
Java开发中有两种方式synchronized机制和JDK5中的ReentrantLock然而在Zookeeper中没有类似于这样的API可以使用Zookeeper通过数据节点表示一个锁例如/exclusive_lock/lock节点被定义位一个锁
获取锁
获取排他锁时所有客户端调用create接口在/exclusive_lock节点下创建临时子节点/exclusive_lock/lockZookeeper保证只有一个客户端创建成功我们认为这个创建成功的客户端就获取到锁其他客户端需要在/exclusive_lock/lock节点上注册一个watcher监听以便实时监听Lock节点变化
释放锁
/exclusive_lock/lock是一个临时节点以下两种情况可认为释放 当前获取锁的客户端机器宕机ZooKeeper上的临时节点会被自动移除正常执行业务逻辑后客户端自行删除临时节点 无论上面两种哪一种Zookeeper删除临时节点后/exclusive_lock/lock上注册Watcher监听的客户端都会收到Watcher通知再次重新发起分布式锁的获取重复以上流程如下图所示排他锁流程
共享锁
共享锁简称S锁又称为读锁同样是一种基本锁如果T1对Q1加上共享锁那么当前事务只能多Q1进行读其他事务也只能对这个数据加共享锁直到所有共享锁都释放。下面借助ZooKeeper来实现共享锁
定义锁
与排他锁一样同样通过ZooKeeper节点表示锁类似/shared_lock/[Hostname]-请求类型-序号的临时顺序节点例如/shared_lock/129.168.1.1-R-0000001那么这个代表一个共享锁
获取锁
客户端到/shared_lock这个节点下创建一个临时顺序节点如果当前是读请求那么就叉棍就如/shared_lock/129.168.1.1-R-0000001的节点如果是写/shared_lock/129.168.1.1-W-0000001
判断读写顺序
根据共享锁定义不同事务可以同一时间多一个数据读而更新只能单独进行我们通过Zoo keep如下方式来进行 创建节点后获取/shared_lock节点下的所有子节点并对该节点注册子节点变化的Watcher监听确定字节节点序号在所有子节点中顺序对于读请求如果没有比字节序号小的子节点或者是所有比字节序号小的子节点都是读表明字节已经成功获取共享锁同时开始读对于写请求如果子不是序号最小的子节点进入等待接收Watcher后重复步骤1
释放锁
与排他锁一致删除释放用如下图解释
羊群效应
在规模不大10台机器作业上面方案能有很高的效率如果规模变大会存如下的这种问题在判断读写顺序的时候会给子节点列表添加watcher监听这样任何一个子节点修改都会有watcher通知信息如下图
192.168.0.1 这条机器首先进行读然后删除节点余下四台机器都能收到子节点移除通知然后从/shared_lock节点上获取一份新子节点列表每个机器判断自己读写顺序其中192。168.0.2这台机器检测自己是最小序号开始写操作余下继续等待继续2 步骤
上面操作是共享锁实现主要步骤当任意一个子节点变化后Watcher通知会给所有其他集群通知然而现实是这个通知其实只对192.168.0.2这个机器有用对其他节点来说无任何作用。后果 分布式竞争中满天飞的无效watcher通知和无效的子节点获取然后进行等待无意义的操作会消耗非常多的系统性能对Zookeeper服务器造成巨大性能影响和网络冲击更严重的是如果同一时间有多个节点对应的客户端完成事务或是事务中断引起节点变化Zookeeper需要在短时间内向其余客户端发送大量事件通知—这就是羊群效应。
改进后的分布式锁实现
主要改动每个竞争者只需关注/shared_lock节点下序号比自己小的节点是否存在即可
客户端create创建类似/shared_lock/[Hostname]-请求类型-序号 的临时节点客户端调用getChildren接口获取所有已经创建子节点列表不注册watcher如果无法获取共享锁调用exist对比比自己小的节点注册watcherid比自己小可用时间戳读请求向比自己序号小的最后一个写请求节点注册watcher监听写请求向比自己序号小的最后一个节点注册watcher监听等待watcher通知继续2 步骤
如下图
注意
并不是一定每次都用改进后的因为改进版本流程复杂如同我们在多线程并发编程中会尽量缩小锁的范围对分布式锁的实现改进也是这样的思路对开发时候来说应该具体情况具体分析集群规模不大网络资源丰富第一张分布式锁简单如果集群达到一定程度希望能精细化处理分布式锁可以用第二种分布式锁实现。
上一篇Zookeeper实践与应用-- Nginx负载均衡差异 下一篇Zookeepe实践与应用–分布队列