首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Redis 中如何实现分布式锁?

Redis 中如何实现分布式锁?

原创
作者头像
代码小李
发布2025-01-28 17:16:32
发布2025-01-28 17:16:32
4250
举报

在 Redis 中实现分布式锁可以通过多种方式,但最常见的是使用 Redis 的原子操作来确保锁的唯一性和互斥性。以下是几种常见的实现方法:

1. 使用 SETNX 命令

SETNX 命令(Set if Not Exists)可以在键不存在时设置键的值。这个命令是原子性的,可以用来实现简单的分布式锁。

示例代码:
代码语言:python
复制
import redis
import time

def acquire_lock(client, lock_name, acquire_timeout=10):
    identifier = str(uuid.uuid4())
    end = time.time() + acquire_timeout
    while time.time() < end:
        if client.setnx(lock_name, identifier):
            return identifier
        time.sleep(0.01)
    return False

def release_lock(client, lock_name, identifier):
    pipe = client.pipeline(True)
    while True:
        try:
            pipe.watch(lock_name)
            if pipe.get(lock_name) == identifier:
                pipe.multi()
                pipe.delete(lock_name)
                pipe.execute()
                return True
            pipe.unwatch()
            break
        except redis.exceptions.WatchError:
            pass
    return False

2. 使用 SET 命令的 EX 和 NX 选项

Redis 2.6.12 及以上版本支持 SET 命令的 EXNX 选项,可以更方便地实现带有超时时间的分布式锁。

示例代码:
代码语言:python
复制
import redis
import time
import uuid

def acquire_lock(client, lock_name, acquire_timeout=10, lock_timeout=10):
    identifier = str(uuid.uuid4())
    end = time.time() + acquire_timeout
    while time.time() < end:
        if client.set(lock_name, identifier, ex=lock_timeout, nx=True):
            return identifier
        time.sleep(0.01)
    return False

def release_lock(client, lock_name, identifier):
    pipe = client.pipeline(True)
    while True:
        try:
            pipe.watch(lock_name)
            if pipe.get(lock_name) == identifier:
                pipe.multi()
                pipe.delete(lock_name)
                pipe.execute()
                return True
            pipe.unwatch()
            break
        except redis.exceptions.WatchError:
            pass
    return False

3. 使用 Redlock 算法

Redlock 算法是由 Redis 作者 Antirez 提出的一种更健壮的分布式锁算法,通过多个 Redis 实例来提高锁的可靠性和可用性。

示例代码:
代码语言:python
复制
import redis
import time
import uuid

class Redlock:
    def __init__(self, nodes, retry_count=3, retry_delay=0.2):
        self.nodes = [redis.StrictRedis(host=node['host'], port=node['port']) for node in nodes]
        self.retry_count = retry_count
        self.retry_delay = retry_delay

    def acquire(self, resource, val, ttl):
        quorum = len(self.nodes) // 2 + 1
        start_time = time.time()

        for retry in range(self.retry_count):
            n = 0
            for node in self.nodes:
                if node.set(resource, val, ex=ttl, nx=True):
                    n += 1
                if n >= quorum:
                    validity_time = ttl - (time.time() - start_time) * 1000
                    if validity_time > 0:
                        return validity_time
            time.sleep(self.retry_delay)

        return 0

    def release(self, resource, val):
        for node in self.nodes:
            try:
                if node.get(resource) == val:
                    node.delete(resource)
            except redis.exceptions.RedisError:
                pass

# 使用示例
nodes = [
    {'host': 'localhost', 'port': 6379},
    {'host': 'localhost', 'port': 6380},
    {'host': 'localhost', 'port': 6381}
]

redlock = Redlock(nodes)
lock_value = str(uuid.uuid4())
lock_ttl = 10  # 锁的超时时间,单位秒

if redlock.acquire('my_lock', lock_value, lock_ttl):
    try:
        # 执行需要加锁的操作
        pass
    finally:
        redlock.release('my_lock', lock_value)

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 使用 SETNX 命令
    • 示例代码:
  • 2. 使用 SET 命令的 EX 和 NX 选项
    • 示例代码:
  • 3. 使用 Redlock 算法
    • 示例代码:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档