Redis锁的介绍

本文介绍了Redis锁的实现,包括使用setnx和set命令加锁,设置超时时间防止死锁,以及使用lua脚本原子解锁。还讨论了公平信号量的实现,以及在Redis服务器挂载和主从切换时的锁问题,并提到了RedLock算法作为更健壮的分布式锁解决方案。

Redis锁的实现:
由于Redis是单进程的,可以简单用setnx这个命令进行加锁操作,谁能操作成功,谁就可以获得锁。简单的代码如下:
def acquire_lock():
    # identifier: 唯一标识客户端
    # lockname 锁名字
    # redis 客户端连接
    if redis.setnx(lockname, identifier):
        return True
    return False
这里有一个问题,就是如果客户端在获得锁的时候崩溃了,服务器就无法再把锁分配给其他客户端使用了,为了解决这个问题,我们可以利用redis的超时特性,给锁加上超时时间
def acquire_lock():
    # identifier: 唯一标识客户端
    # lockname 锁名字
    # redis 客户端连接
    # timeout 超时时间
    if redis.setnx(lockname, identifier):
        redis.expire(lockname, timeout)
        return True
    elif not redis.ttl(lockname):
        redis.expire(lockname, timeout)
        ret

### Redis事务介绍 Redis事务是一种将多个命令打包,按顺序执行的机制。使用`MULTI`标记事务开始,之后可发送多条命令,Redis会将这些命令存入队列,调用`EXEC`时统一执行。若要取消事务,可使用`DISCARD`。还能通过`WATCH`监视一个或多个键,若事务执行前被监视的键发生变化,事务将中止,以此防止并发修改引起的数据不一致问题[^4]。 ### Redis介绍 Redis用于解决并发访问问题,有乐观和悲观等类型。乐观假定多个客户端同时访问同一数据时冲突概率较低,读取数据时不加,更新前检查数据是否被其他客户端修改;悲观则在操作数据前就加,防止其他客户端同时操作。此外,还有基于`setnx`特性实现的分布式锁,虽Redis本身未提供此特殊,但可利用`setnx`解决业务场景中的并发问题[^1][^2][^3]。 ### Redis事务使用场景 - **批量操作**:需要一次性执行多个命令时,可将这些命令放在事务中,保证按顺序执行。如电商系统中,用户下单时同时扣减库存、增加订单记录、更新用户积分等操作,可通过事务确保数据一致性和操作顺序性。 - **防止数据竞争**:高并发场景下,使用`WATCH`监控关键键,避免脏写。例如多个客户端同时对同一账户操作,使用`WATCH`监控该账户键,若事务执行前键被其他客户端修改,事务会中断,保证数据正确性,实现简单乐观机制[^1][^2]。 ### Redis使用场景 - **资源互斥访问**:多个客户端对同一资源进行写操作时,使用保证同一时间只有一个客户端能操作,防止数据冲突。如多个进程同时修改Redis中的库存数据,使用分布式锁确保只有一个进程能修改。 - **并发控制**:在并发场景下,通过控制对共享资源的访问顺序。例如在分布式系统中,多个服务实例可能同时访问同一个Redis缓存,使用保证数据的一致性和完整性。 ### Redis事务和Redis的区别 - **功能侧重点**:事务主要用于将多个命令打包按顺序执行,保证操作的顺序性和一定程度的原子性;主要用于解决并发访问问题,控制对共享资源的访问权限,保证数据的一致性和完整性。 - **实现机制**:事务通过`MULTI`、`EXEC`、`DISCARD`、`WATCH`等命令实现;则基于不同的算法和命令,如乐观基于`WATCH`,分布式锁利用`setnx`特性实现。 - **使用方式**:事务将多个命令组合在一个事务块中执行;在操作共享资源前加,操作完成后释放。 ### 代码示例 #### Redis事务示例 ```python import redis r = redis.Redis(host='localhost', port=6379, db=0) # 开始事务 pipe = r.pipeline() pipe.multi() # 执行命令 pipe.set('key1', 'value1') pipe.set('key2', 'value2') # 执行事务 result = pipe.execute() print(result) ``` #### Redis示例(基于setnx) ```python import redis import time r = redis.Redis(host='localhost', port=6379, db=0) # 加 lock_key = 'my_lock' lock_value = 'unique_value' lock_acquired = r.setnx(lock_key, lock_value) if lock_acquired: try: # 模拟操作 print("获取到,执行操作") time.sleep(2) finally: # 释放 r.delete(lock_key) print("释放") else: print("未获取到") ```
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值