简单使用redis分布式锁

python使用redis分布式锁

1.使用分布式锁需要注意的细节:
 (1)互斥性。任何时刻只有一个客户端能持有锁
 (2)避免死锁。即使一个客户端持有锁的期间崩溃而没有主动释放锁,也需要保证后续其他客户端能够加锁成功
 (3)加锁和解锁必须是同一个客户端,客户端自己不能把其他客户端加的锁给释放了。

2.使用redis实现分布式锁,主要是使用了3个命令 setnx + expire + del, 但是注意这些命令不具备原子性,
  比如一个线程在setnx后抛出异常导致没有执行expire,此时会导致锁不释放并一直阻塞,所以一定要保证这
  些命令搭配使用的原子性

3.了解redis的setnx命令,setnx是SET if Not eXists的简称。
  setnx命令的返回特性:命令在设置成功时返回 1 , 设置失败时返回 0 
  中文文档地址:http://redisdoc.com/string/setnx.html
  英文文档地址:https://redis.io/commands/setnx

  了解redis的expire命令,设置锁过期时间
  中文文档地址:http://redisdoc.com/expire/expire.html
  英文文档地址:https://redis.io/commands/expire

  了解redis的del命令,删除并释放锁
  中文文档地址:http://redisdoc.com/database/del.html
  英文文档地址:https://redis.io/commands/del

4.代码
def acquire_lock(conn, lock_name, acquire_time=125, time_out=120):
    """
    Acquire a distribute lock according to redis
    :param conn: type redis.client.Redis, redis connection
    :param lock_name: type str, lock name
    :param acquire_time: type int, The time the client waits to acquire the lock
    :param time_out: type int, lock timeout time
    :return: return identifier if get lock, else return false
    """
    identifier = str(uuid.uuid4())
    end = time.time() + acquire_time
    lock = "string:lock:" + lock_name
    while time.time() < end:
        if conn.set(lock, identifier, ex=time_out, nx=True):
            return identifier
        time.sleep(1)
    return False


def release_lock(conn, lock_name, identifier):
    """
    Release a redis distributed lock to allow other thread acquire the lock
    :param conn: type redis.client.Redis, redis connection
    :param lock_name: type str, lock name
    :param identifier: type str, lock value - identifier(uuid)
    :return: return True if lock release success, else False
    """
    unlock_script = """
        if redis.call("get",KEYS[1]) == ARGV[1] then
            return redis.call("del",KEYS[1])
        else
            return 0
        end
        """
    lock = "string:lock:" + lock_name
    unlock = conn.register_script(unlock_script)
    return unlock(keys=[lock], args=[identifier])


5.建议参考官网(https://redis.io/topics/distlock)这里有一些基于不同语言(如python、java等)实现的第三方的相对稳定的redlock


参考:
  https://zhuanlan.zhihu.com/p/112016634
  https://www.cnblogs.com/zknublx/p/11722074.html

问题:
  安全性,如果redis节点挂了或slave提升为master期间会出现问题
  性能,acquire time自旋,如果持久获取不到锁会导致线程阻塞,如果只是需要乐观锁可以这样试试。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值