本文摘自PHP中文网,作者尚,侵删。

使用Redis锁处理并发问题,保证多进程仅有一个实例在运行,当运行中的实例down了后其它实例中的一个能顶上来,保证有且仅有一个实例在运行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | import redis
r = redis.Redis(...)
last_heart = 0 # 记录上一次得到的锁心跳
free_lock_try = 6 # 锁无心跳的最大次数
while not r.setnx( 'mylock' , 1):
now_heart = r.get( 'mylock' )
print (f "没获取到锁,now_heart={now_heart},last_heart={last_heart},free_lock_try={free_lock_try}" )
if now_heart == last_heart:
free_lock_try = free_lock_try - 1
if free_lock_try == 0: # 锁已经1分钟没有心跳了
old_heart = r.getset( 'mylock' , 1) # 将lock重置为1,并返回set之前的心跳值
if old_heart < now_heart:
time.sleep(10)
continue
else :
break # 成功获取到锁,退出循环
else :
free_lock_try = 6 # 锁有心跳,重置free_lock_try值
last_heart = now_heart
time.sleep(10)
def producer_exit():
"" "程序正常退出时候自动清理锁" ""
r. delete ( 'mylock' )
import atexit
atexit.register(producer_exit)
# 业务代码
while True:
r.incr( 'mylock' ) # 让锁心跳加一
...
|
我们来看看这段程序都解决了并发锁中的哪些问题:
1、高并发下,多个进程无法同时获取到锁。这里使用的是redis.setnx,如果锁已经存在,其他进程是无法重置锁并获取到锁的。另外当多个进程同时发现有锁已经没有心跳了,使用的是redis.getset将心跳重置为1,都能set成功,但是get出来的值多个进程是不一样的,只有真正获取到锁的进程返回的是之前进程的心跳,而其他进程获取到的都是1。
2、有锁进程正常退出,可以使用atexit注册进程退出函数删除锁,这里也可以不要,不过下次启动得等新的进程等待几次心跳
3、有锁进程意外退出,退出后心跳不再增加,超过free_lock_try次数后,其他进程会重新设置并获取锁
4、所有进程全都意外退出,这个问题不是锁来关心的,可以使用supervisor进行守护进程。
更多redis知识请关注redis入门教程栏目。
以上就是使用Redis锁处理并发问题的方法的详细内容,更多文章请关注木庄网络博客!
相关阅读 >>
Redis防坑指南――事务
Redis用户验证设置方法
连接Redis需要密码吗
Redis实现批量删除的命令介绍
php+Redis实现加锁与解锁操作
Redis注册成window服务的方法介绍
Redis怎么保证高可用
Redis能代替mysql吗
使用Redis实现一个安全可靠的分布式锁
Redis缓存怎么和数据库同步
更多相关阅读请进入《Redis》频道 >>
机械工业出版社
本书主要讲述了数据模型、基于对象的数据库和XML、数据存储和查询、事务管理、体系结构等方面的内容。
转载请注明出处:木庄网络博客 » 使用Redis锁处理并发问题的方法