阿里云服务器建网站贵州省建设厅网站首页
web/
2025/9/28 13:11:09/
文章来源:
阿里云服务器建网站,贵州省建设厅网站首页,小学学校网站模板,怎么做关于狗的网站分布式锁概念
为什么使用分布式锁
假设有这样一个场景#xff0c;双十一抢iphone15ProMax手机场景#xff0c;可以抢多台。操作数据库接口如下#xff1a; void reduceInventory(Long id,int count) {//1.拿到数量信息Product product mapper.selectById(id);//2.修改数量…分布式锁概念
为什么使用分布式锁
假设有这样一个场景双十一抢iphone15ProMax手机场景可以抢多台。操作数据库接口如下 void reduceInventory(Long id,int count) {//1.拿到数量信息Product product mapper.selectById(id);//2.修改数量信息int newCount product.getProductCount() - count;product.setProductCount(newCount);int i mapper.updateById(product);System.out.println(修改成功- i);}在单个应用情况下可以使用synchronized或者lock锁解决并发问题因为只有这一个应用可以调用这个接口。那么在微服务应用下呢多个请求 同时访问这个接口步骤1是可以同时执行的在同一时间可能拿到的数量是相同的假设A服务和B服务各有一个请求访问这个接口那么A应用要抢 5个B应用要抢1个这样就导致A应用要更新数据库的时候数量是95B应用要更新的数量是99不管谁先拿到数据库的锁都会后拿到数据库锁的 覆盖掉前面的数据导致数据不正确。那么如何解决这个问题呢答案就是分布式锁。 加分布式锁的本质就是保证步骤1和步骤2这个逻辑或者说这块代码无论有多少个并发请求必须保证同步执行。而且无论多少个服务都能通过 一个公用的组件来控制代码同步执行比如MySQL、Redis、zookeeper。任何一个服务都能访问到它而不是通过synchronized或者lock锁 因为每个服务的synchronized或者lock锁都是只有当前服务能访问不能实现服务之间的排他性。 分布式锁有三种实现方式
1. MySQL实现分布式锁
原理 在数据库层面加锁处理在一个线程修改数据查询数据的时候进行for update处理。这样其他线程在查询数据的时候就会阻塞必须等当前 线程处理完才能执行for update查询语句。 步骤 开启事务执行select * from table where id ? for update语句提交事务 问题 一旦有某个线程处理逻辑时开启了事务但是抛出异常了那么就会导致事务无法提交其他线程永远拿不到数据库锁导致死锁问题。 2.RedisRUA脚本实现分布式锁
原理 redis中有nx 和 ex操作其中nx表示当前key不存在时才执行成功返回0表示失败返回1表示成功ex表示过期时间。当加锁的时候执行nx操作如果当前有线程持有锁则设置失败返回0否则成功返回1.释放锁的时候执行del操作。ex可以防止死锁问题如果有个线程执行setnx操作了由于异常不执行del释放锁操作那么其他线程永远无法拿到锁。 要解决的问题
如何避免死锁问题 设置ex过期时间。 如何保证锁不会被其他线程释放 通过redis存储的value来控制将value作为线程的唯一标识只有当前线程的解锁标识和设置的value相同时才能删除当前key。 如何保证在释放锁时如何保证查询value值、必对value值、删除key操作的原子性 使用RUA脚本f(redis.call(‘get’, KEYS[1]) ARGV[1]) then return redis.call(‘del’, KEYS[1]) end return 0传入 客户端的唯一标识和redis拿到的value对比如果相同则删除key否则不删除。 如何评估redis中key的过期时间 使用守护线程 守护线程的特点是当主线程销毁时守护线程随机销毁在加锁的时候开启一个守护线程。守护线程的操作是在key将要失效的时候进行续期操作。这样做的好处是在解决了死锁问题的同时如果业务逻辑执行比较慢的话也不会导致锁自动失效的问题 Redis宕机问题
假设一个客户端在加锁的时候master实例突然宕机没有向slave同步数据其中一个slave升级为master,另一个实例重新获取锁这种情况下锁的安全性被打破。 redis作者提出RedLock概念 客户端记录当前时间戳T1,并设置锁的TTL时间在服务器创建5个redis实例非集群不存在数据同步问题。依次从5个redis实例去获取锁相同的key-value,获取锁时要设置网络连接和响应的超时时间该时间要小于锁TTL时间避免客户端死等。客户端记录最后一个获取锁成功的时间戳(因为有可能在五个Redis中有宕机发生就获取锁失败了)T2和获取锁成功的个数n,其中n要大于等于3半数以上节点获取重构且T2-T1要小于TTL才算获取成功。锁的时间为TTL - 取锁的时间如果加锁失败客户端向所有Redis实例发送解锁请求。 其中有三个要解决的问题NPC Network Delay: 网络延迟问题Process Pause: 进程暂停问题Clock Drift: 时钟漂移问题客户端服务器和Redis服务器时间不一致 3. Zookeeper实现分布式锁
Zookeeper分布式锁时基于临时顺序节点实现的. 要解决的问题 如何实现互斥性Zookeeper中的节点类似文件系统的目录结构当对其中一个节点加锁其他线程就不能再创建了。如何加锁解锁当客户端连接Zookeeper后创建节点断开连接删除节点如何解决高可用问题使用顺序节点watch机制当客户端加锁时会在目录下创建一个字子点并记录创建顺序节点然后判断创建的顺序节点是否为第一个节点如果是加锁成功如果不是watch上一个节点以此类推 如果加锁成功的客户端断开连接那么监听该顺序节点的客户端就可以去获取锁这样就减轻了高并发下的zookeeper压力实现高可用。 实现原理 创建临时顺序节点每个客户端访问zk会创建临时节点例如/locks下创建一个临时顺序节点。获取所有子节点并排序客户端通过getChildren获取/locks下的所有子节点并对这些子节点按照它们的序号进行排序。判断锁的拥有者客户端检查它创建的节点是不是排序后的第一个节点如果是则获取到锁如果不是则监视排序后的前一个节点。等待或者阻塞如果这个节点不是第一个客户端就会注册对前一个节点的监视器并进入等待状态直到前一个节点被删除释放锁。释放锁当客户端完成操作释放锁时会删除它创建的临时节点然后通知监视器上的等待节点。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/83347.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!