并发-分布式锁质量保障总结

并发-分布式锁质量保障总结

实现分布式锁的主流方法

三种主流方法:

  • 基于数据库(MySQL)实现分布式锁

    • 基于MySQL锁表
    • 数据库版本号乐观锁
  • 基于缓存(redis)实现分布式锁

  • 基于zookeeper/etcd实现分布式锁

实现方法优点缺点适用场景
MySQL数据库表易于理解、易于实现容易出现单点故障、死锁、性能低、可靠性低并发量低、性能要求低的场景
redis分布式锁性能高、易于实现、可跨集群部署,无单点故障锁失效时间控制不稳定,稳定性低于zookeeper高并发、高性能场景
zookeeper分布式锁无单点故障、可靠性高、不可重入、无死锁问题实现复杂,性能低于分布式锁适用于大部分分布式场景,除对性能要求极高的场景

MySQL数据库表的乐观锁适用于读多写少的场景且共享资源为数据库的单行数据;MySQL表锁实现的锁一般都不推荐使用;ZooKeeper分布式锁虽然适用于大部分分布式场景,但是由于其实现复杂度相对较高以及需要额外引入中间件,在大部分业务场景中的应用比较少,而基于Redis的缓存分布式锁应用较为广泛;但是具体业务实现采用哪种类型的分布式锁,还是需要基于当前的业务特性来进行决定;

redis分布式锁注意事项

Redis通常可以使用setnx(key,value)函数来实现分布式锁。key和value就是基于缓存的分布式锁的两个属性,其中key表示锁id。setnx函数返回1表示获得锁,返回0表示其他服务器已经获得了锁;

redis key
  • 全面梳理业务场景,对于同一共同资源,key要保持一致
  • key是识别共享资源的唯一键,key既要锁住当前共享资源又不能影响其他资源
锁释放
  • 锁一定需要明确释放,try/finally结构加解锁,finally内释放锁
  • 锁只能被加锁对象释放,避免出现下图问题,A加锁被B释放,导致C拿到锁
    锁释放
锁超时
  • 一定要设置key超时间;
  • 超时时间的设置一般来讲大于服务的最大执行时间即可,在种极端情况处理方式如下2种:
    • 可以再开启一个线程,为当前超时时间续时,但增加了系统的复杂度;
    • 将过期时间设置非常长,一定能保证逻辑在锁释放之前能够执行完成;此方案简单但是有缺陷,当遇到系统突发异常时,锁无法被释放,阻断业务执行,很有可能造成故障;
锁力度

如果针对某个共享资源的写是基于另外一个共享资源的值计算而来,那么锁的范围必须包含读共享资源;范围不包含读共享资源会导致脏读,最终导致数据的错误,如下图所示,Client B最终计算的B的结果就是错误的。
锁粒度

锁获取失败

由于其他线程已经获取到了锁,当前线程获取锁失败后有3种处理方式:

  • 异常抛出让用户重试;
  • 通过自旋再次进行抢锁;
  • 发布订阅,订阅锁释放消息;

在并发度低的场景下异常抛出以及自旋抢锁都可以,在高并发场景下异常抛出和自旋抢锁都不可取。

MySQL数据库锁
数据库版本号乐观锁

在数据库的表中需要包含一个数字类型的字段version,读取数据时把version字段读出来,更新数据时判断当前version是否等于读取出来的version,并对当前version+1;如果等于就更新成功,不等于表示数据已过期更新失败。例如以积分体系为例,存在多种场景增加积分,通过乐观锁来保证数据的正确性。
数据库版本号乐观锁
乐观锁注意点:

  • where条件一定要命中索引(最好是主键索引或唯一索引),否则会锁表;
  • update table set 必须包含version = version + 1;
  • update 返回结果为0时,一定要根据业务场景进行相应的处理,自主重试或者抛异常;
基于MySql锁表

创建一张锁表,对临界资源做唯一性约束,通过增加一条记录对某一资源上锁,释放锁时删除记录;一般不推荐此种用法。

参考资料

https://mp.weixin.qq.com/s?__biz=MzIzOTU0NTQ0MA==&mid=2247507645&idx=1&sn=8cddd40b604dbed3aad0b864d2fe2d76&chksm=e92ae3b2de5d6aa4e3c3b7a8635c92a58e6f62ce897ed64d825fbbd5bfb19951512629452ed8&mpshare=1&scene=1&srcid=0307D1CcU252mtTqVbs0dCzB&sharer_sharetime=1646738073957&sharer_shareid=484a2bec99a6069be706eea0c87ff123&version=4.0.0.6024&platform=win#rd

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值