使用Redis锁处理并发问题的方法


本文摘自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宕机了怎么办

linux查看Redis是否启动

Redis实现简单的条件查询

Redis是数据库吗

Redis整数集不能降级?为什么?

Redis缓存中间件基础知识介绍

Redis自增计数

更多相关阅读请进入《Redis》频道 >>


数据库系统概念 第6版
书籍

数据库系统概念 第6版

机械工业出版社

本书主要讲述了数据模型、基于对象的数据库和XML、数据存储和查询、事务管理、体系结构等方面的内容。



打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...