视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
使用Redis锁处理并发问题的方法
2020-11-09 06:53:46 责编:小采
文档

使用Redis锁处理并发问题,保证多进程仅有一个实例在运行,当运行中的实例down了后其它实例中的一个能顶上来,保证有且仅有一个实例在运行。

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入门教程栏目。

下载本文
显示全文
专题