Redis实现分布式锁和等待序列

本文探讨了如何使用Redis实现分布式锁,并详细介绍了在并发控制中利用Redis构建等待序列的策略,确保了多线程环境下的资源安全与高效调度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

package com.test
    import redis.clients.jedis.Jedis;
    import java.util.Collections;
    import java.util.List;
    /**
     * @desc redis队列实现方式
     * @anthor 
     * @date 
     **/
    public class RedisUcUitl {
        private static final String LOCK_SUCCESS = "OK";
        private static final String SET_IF_NOT_EXIST = "NX";
        private static final String SET_WITH_EXPIRE_TIME = "PX";
        private static final Long RELEASE_SUCCESS = 1L;
        private RedisUcUitl() {
        }
        
        /**
         * 存储redis队列顺序存储 在队列首部存入
         * @param key   字节类型
         * @param value 字节类型
         */
        public static Long lpush(Jedis jedis, final byte[] key, final byte[] value) {
            return jedis.lpush(key, value);
        }
    
        /**
         * 移除列表中最后一个元素 并将改元素添加入另一个列表中 ,当列表为空时 将阻塞连接 直到等待超时
         * @param srckey
         * @param dstkey
         * @param timeout 0 表示永不超时
         * @return
         */
        public static byte[] brpo
### 使用 Redis 实现分布式锁时需注意的关键问题 #### 锁的可靠性安全性 为了确保分布式锁的安全性,在多个客户端竞争同一把锁的情况下,只有第一个请求成功的客户端才能获得这把锁。SETNX 命令用于尝试创建键值对,如果键不存在则成功返回1并设置该键;反之,则失败返回0[^2]。 #### 设置合理的过期时间 为了避免死锁情况的发生,应当给锁设定一个合适的超时期限。当持有锁的操作未能及时释放锁资源时,其他等待中的进程能够有机会获取到锁继续执行下去。然而,过短的时间可能导致误判丢失锁的情况发生,因此需要根据业务逻辑合理评估最长时间消耗来决定这个参数的具体数值。 #### 解决网络分区带来的影响 在网络不稳定或存在延迟的情况下,可能会遇到部分节点之间通信中断的现象即所谓的“脑裂”。此时即使某些实例已经无法访问但仍保持有未到期的有效锁状态,而新选举出来的协调者又会重新分配新的相同名称下的锁对象造成冲突。为此官方推荐采用 Redlock 算法,在至少 N/2+1 (N>=5) 台不同物理位置上的 Redis Server 上同时加锁以提高容错能力[^1]。 #### 防止锁重入风险 对于同一个客户端而言,在已拥有某项特定资源对应的锁之后再次申请相同的锁并不会引起异常而是应该被允许直接操作受保护的数据结构。这就涉及到如何区分来自同源但可能携带不同上下文信息的任务之间的关系处理机制设计了。通常做法是在构建唯一标识符时加入线程ID或其他能表征调用链路特征的因素进去作为附加条件之一。 ```python import redis from time import sleep, time client = redis.StrictRedis(host='localhost', port=6379) def acquire_lock(lock_name, acquire_timeout=10): identifier = str(uuid.uuid4()) end = time() + acquire_timeout while True: if client.setnx(lock_name, identifier): # 尝试获取锁 client.expire(lock_name, 10) # 成功后立即设定了TTL防止死锁 return identifier elif not client.ttl(lock_name): # 如果发现锁没有设置有效期限就补上 client.expire(lock_name, 10) sleep(0.001) if time() > end: # 超时退出循环不再争夺此锁 return False identifier = acquire_lock('my_resource') if identifier is None or identifier == False: print("Failed to get lock.") else: try: pass # 执行临界区代码... finally: release_lock('my_resource', identifier) def release_lock(lock_name, identifier): with client.pipeline() as pipe: while True: try: pipe.watch(lock_name) # 开始监视某个key的变化 if pipe.get(lock_name) != identifier.encode(): pipe.unwatch() break pipe.multi() # 进入事务模式 pipe.delete(lock_name) # 删除指定名字的锁记录 pipe.execute() # 提交命令序列至服务器端完成解锁动作 break except redis.WatchError: # 当前持有的锁已被更改放弃此次删除尝试 continue ```
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值