首页 > 数据库 >Redis实现分布式锁

Redis实现分布式锁

时间:2022-10-31 16:13:11浏览次数:74  
标签:实现 lock self Redis timeout time release now 分布式

import redis
import time

S_REDIS = redis.Redis(
    host='10.127.0.0',
    port='8088',
    db=9,
    password='test',
    decode_responses=True,
    retry_on_timeout=True,
    health_check_interval=10,
    socket_timeout=120,
    socket_keepalive=True
)


class ShareLock:
    def __init__(self, key, timeout=60):
        """
        :param key: 共享锁的名称
        :param timeout: 共享锁的超时时间
        """
        self.redis = S_REDIS
        self.lock_name = key
        self.timeout = timeout

    def acquire(self):
        # 这里时间值不能用datetime,应该是时间戳函数time.time()
        # now = begin = datetime.now()
        now = begin = time.time()
        while now - begin < self.timeout:
            # setnx并没有设定键的过期时间,所以可以使用两种方式进行处理,方式1:expire(key, ttl), 方式2:业务侧判断锁过期
            flag = self.redis.setnx(self.lock_name, now + self.timeout + 1)
            # setnx返回值为1,代表获取到分布式锁
            if flag == 1:
                return True
            # 接下来使用业务侧判断锁过期方式来实现分布式锁
            lock_release_time = self.redis.get(self.lock_name)
            if not lock_release_time:
                time.sleep(1)
                continue
            # 在判断到锁过期的情况下,如果其他进程已经重新获取到锁,这个是考虑的情况1,情况2就是如果没有设置过期时间,获取锁的进程
            # 没有release锁的情况,这个时候我们判断超时后需要重新set
            if now > int(lock_release_time):
                # 如果超时,当前进程刷新lock_name对应的时间,代表获取到锁, 其他进程等待
                old_lock_time = self.redis.getset(self.lock_name, now + self.timeout + 1)
                # 如果锁释放了,getset的值为none,此时重新走setnx逻辑获取锁
                if old_lock_time and int(old_lock_time) == int(lock_release_time):
                    #  这里要考虑一种特殊情况,如果两个进程都走进去当前逻辑, 此时需要再进一步判断锁的时间, 判断确实是当前进程重置了锁过期时间
                    return True
            time.sleep(1)
            now = time.time()
        return False

    def release(self):
        """
        :return:
        """
        self.redis.delete(self.lock_name)

    def __enter__(self):
        self.acquire()

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.release()

 

import redis
import time

S_REDIS = redis.Redis(
host='10.127.0.0',
port='8088',
db=9,
password='test',
decode_responses=True,
retry_on_timeout=True,
health_check_interval=10,
socket_timeout=120,
socket_keepalive=True
)


class ShareLock:
def __init__(self, key, timeout=60):
"""
:param key: 共享锁的名称
:param timeout: 共享锁的超时时间
"""
self.redis = S_REDIS
self.lock_name = key
self.timeout = timeout

def acquire(self):
# 这里时间值不能用datetime,应该是时间戳函数time.time()
# now = begin = datetime.now()
now = begin = time.time()
while now - begin < self.timeout:
# setnx并没有设定键的过期时间,所以可以使用两种方式进行处理,方式1:expire(key, ttl), 方式2:业务侧判断锁过期
flag = self.redis.setnx(self.lock_name, now + self.timeout + 1)
# setnx返回值为1,代表获取到分布式锁
if flag == 1:
return True
# 接下来使用业务侧判断锁过期方式来实现分布式锁
lock_release_time = self.redis.get(self.lock_name)
if not lock_release_time:
time.sleep(1)
continue
# 在判断到锁过期的情况下,如果其他进程已经重新获取到锁,这个是考虑的情况1,情况2就是如果没有设置过期时间,获取锁的进程
# 没有release锁的情况,这个时候我们判断超时后需要重新set
if now > int(lock_release_time):
# 如果超时,当前进程刷新lock_name对应的时间,代表获取到锁, 其他进程等待
old_lock_time = self.redis.getset(self.lock_name, now + self.timeout + 1)
# 如果锁释放了,getset的值为none,此时重新走setnx逻辑获取锁
if old_lock_time and int(old_lock_time) == int(lock_release_time):
# 这里要考虑一种特殊情况,如果两个进程都走进去当前逻辑, 此时需要再进一步判断锁的时间, 判断确实是当前进程重置了锁过期时间
return True
time.sleep(1)
now = time.time()
return False

def release(self):
"""
:return:
"""
self.redis.delete(self.lock_name)

def __enter__(self):
self.acquire()

def __exit__(self, exc_type, exc_val, exc_tb):
self.release()



标签:实现,lock,self,Redis,timeout,time,release,now,分布式
From: https://www.cnblogs.com/kevin-zsq/p/16844650.html

相关文章