Python 多线程之 Redis 分布式锁_使用redis实现分布式锁及其优化

liftword4个月前 (02-26)技术文章29

前言

在很多互联网产品应用中,有些场景需要加锁处理,例如:双11秒杀,全局递增ID,楼层生成等等。

大部分的解决方案是基于 DB 实现的,Redis 为单进程单线程模式,采用队列模式将并发访问变成串行访问,且多客户端对 Redis 的连接并不存在竞争关系。

其次 Redis 提供一些命令SETNX,GETSET,可以方便实现分布式锁机制。


Python代码实现

import time
import redis
import threading

#使用连接池方式连接redis
redis_pool=redis.ConnectionPool(host="127.0.0.1",port=6379)
redis_conn=redis.Redis(connection_pool=redis_pool)

#定义redis类
class RedisLock():
    def __init__(self):
        self.redis_conn = redis_conn
        print("init the redis connection")

    #获取锁
    def get_lock(self,name,value):
        while True:
            # set(name, value, ex=None, px=None, nx=False, xx=False)
            # nx - 如果设置为True,则只有name不存在时,当前set操作才执行
            # ex - 过期时间(秒)
            result=self.redis_conn.set(name,value,nx=True,ex=3)
            # print(result)
            if(result):
                # 获取到result后就终止while循环
                break
            # time.sleep(0.5)

    #释放锁
    def release_lock(self,name,value):
        #获取原name key对应的value
        old_value = redis_conn.get(name)
        print("--------------------------------the key =%s ;the name=%s"%(name,old_value))
        #判断原value 与 要释放的值是否相同
        if(old_value == value):
            #相同就从redis里面释放
            self.redis_conn.delete(name)
            print("release the lock is success")

def redis_lock_test(lock,name,value):
    try:
        print("% --start to work"%name)
        print("% --ready get the lock and execute lock operation"%name)
        lock.get_lock(name,value)#这里是获取锁操作
        print("% --get the lock and continue to operation"%name)
    except Exception as e:
        print("the exception is:%s"%str(e))
    finally:
        print("% --ready release the lock"%name)
        lock.release_lock(name,value)#最终必须释放锁操作
        print("% --release the lock is over"%name)

if __name__ == '__main__':
    start_time=time.time()
    rs=RedisLock()
    tasks=[]
    for i in range(1,3):
        # 创建线程
        t = threading.Thread(target=redis_lock_test(rs,"task-name%"%i,"lock%d"%i))
        # 将创建的线程放入列表
        tasks.append(t)
        # 启动线程
        t.start()
    #这里没有设置守护线程且没有设置join函数的timeout参数时,主线程将会一直等待,直到子线程全部结束,主线程才结束,程序退出
    [t.join() for t in tasks]
    print("total waster time is:",time.time()-start_time)


注意:

1. thread.setDaemon(True) 当设置守护线程 join 函数的参数 timeout=2 时,主线程将会等待多个子线程 timeout 的累加和这样的一段时间,时间一到,主线程结束,杀死未执行完的子线程,程序退出。

2. 当没有设置守护线程且 join 函数的参数 timeout=2 时,主线程将会等待多个子线程 timeout 的累加和这样的一段时间,时间一到主线程结束,但是并没有杀死子线程,子线程依然可以继续执行,直到子线程全部结束,程序退出。

相关文章

三分钟掌握Python 中最常用的 10 种 Set 方法

Python 中的集合至关重要,也是 Python 中最常用的内置数据类型之一。集合具有一些主要属性。集合中的元素必须是唯一的。套装中不允许有重复项。它们是无序的设置项目不可更改,但您可以删除和添加新...

Python 集合(Set)的十个经典案例_python 集合 discard

Python 集合(Set)是一种无序、可变的数据结构,存储不重复的元素。集合类似于数学上的集合概念,可以进行交集、并集、差集等运算。1. 创建集合可以使用花括号 {} 或 set() 函数创建集合。...

神奇的 Python set():如何让重复元素无处可藏

前言如果你还没认真研究过 Python 中的集合(set)类型,那你可真是错失了一项神器!集合不仅能让你的代码变得更高效,还能避免一堆重复数据让你头疼。每当你用 Python 编程时,数据就像是无序的...

Python集合类型Set详细总结_python里面集合

(一)Python集合数据类型Set总结-1 1、set特点set 可以过滤重复元素,本身是无序的(元素顺序是混乱的)不重复的示例-1:set = {1,2,2,3,4,4,5,6,7,7}#输出se...

Python set_python set和list的区别

Python 也包含有 集合 类型。集合是由不重复元素组成的无序的集。它的基本用法包括成员检测和消除重复元素。集合对象也支持像 联合,交集,差集,对称差分等数学运算。集合结构如下:set1 = {'h...

Python里的set和dict,如何选择用哪一个?

set和dict的共同特点就是无序。set存储的元素是唯一的,如果重复就会自动去除。˃˃˃ aset={1,2,3,3}˃˃˃ print(aset){1, 2, 3}dict的key必须是唯一的,但...