作者:lightcity 2021-09-10 21:25:43
存储
存储软件
分布式
Redis 最近,有两台容器,当程序运行时,会发送多份通知,那么需要保证同一时刻只有一个进程(一台容器)来运行,此时用分布式锁解决该问题。
公司主营业务:网站制作、成都网站设计、移动网站开发等业务。帮助企业客户真正实现互联网宣传,提高企业的竞争能力。创新互联是一支青春激扬、勤奋敬业、活力青春激扬、勤奋敬业、活力澎湃、和谐高效的团队。公司秉承以“开放、自由、严谨、自律”为核心的企业文化,感谢他们对我们的高要求,感谢他们从不同领域给我们带来的挑战,让我们激情的团队有机会用头脑与智慧不断的给客户带来惊喜。创新互联推出揭阳免费做网站回馈大家。
在业务开发中像订单写入,一般需要单线程来保证订单写入数据库,防止数据多次被插入。
最近,有两台容器,当程序运行时,会发送多份通知,那么需要保证同一时刻只有一个进程(一台容器)来运行,此时用分布式锁解决该问题。
业界也有许多解决这种方案,这里以redis分布式锁来解决。
简单来说就是采用golang redis库实现下面方案即可。
2.1 setnx+expire
setnx key value,将key设置为value,当键不存在时,才能成功,若键存在,什么也不做,成功返回1,失败返回0。
SETNX实际上就是SET IF NOT Exists的缩写。
- setnx key val
- expire key seconds
但是,上述两个操作不具有原子性,如果执行完第一条指令应用异常或者重启了,锁将无法过期。
2.2 lua脚本
既然是原子性无法保证,那就采用执行lua脚本的原子性,将上述两个操作封装到lua脚本中便可以实现。
- if redis.call('setnx',KEYS[1],ARGV[1]) == 1 then
- redis.call('expire',KEYS[1],ARGV[2])
- else
- return 0
- end;
2.3 携带TTL的set
从 Redis 2.6.12 版本开始, SET 命令的行为可以通过一系列参数来修改。
- SET key value [EX seconds]
- [PX milliseconds] [NX|XX]
将字符串值 value 关联到 key 。
如果 key 已经持有其他值, SET 就覆写旧值,无视类型。
对于某个原本带有生存时间(TTL)的键来说, 当 SET 命令成功在这个键上执行时, 这个键原有的 TTL 将被清除。
直接使用可能存在如下问题:
例如:如果线程 A 成功获取锁并设置过期时间 30 秒,但线程 A 执行时间超过了 30 秒,锁过期自动释放,此时线程 B 获取到了锁,线程 A 和线程 B 并发执行。
A、B 两个线程发生并发显然是不被允许的,一般有两种方式解决该问题:
解决方案:1)确保代码在过期时间之前释放。2)为获取锁的线程增加守护线程,为将要过期但未释放的锁增加有效时间。
锁被别的线程误删除。
例如:如果线程 A 成功获取到了锁,并且设置了过期时间 30 秒,但线程 A 执行时间超过了 30 秒,锁过期自动释放,此时线程 B 获取到了锁;随后 A 执行完成,线程 A 使用 DEL 命令来释放锁,但此时线程 B 加的锁还没有执行完成,线程 A 实际释放的线程 B 加的锁。
解决方案是:通过在 value 中设置当前线程加锁的标识,在删除之前验证 key 对应的 value 判断锁是否是当前线程持有。可生成一个 UUID 标识当前线程,使用 lua 脚本做验证标识和解锁操作。
学习文章:
https://xiaomi-info.github.io/2019/12/17/redis-distributed-lock/
https://zhuanlan.zhihu.com/p/115848078
文章题目:Redis分布式锁解决多进程/多线程下单个进程/单个线程运行
本文地址:http://www.stwzsj.com/qtweb/news48/8048.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联