Redisson里有公平锁吗?他的实现原理是什么样子的?
1 个回答
永远喜欢简单而真诚的人。玉鼎真人Redisson **支持公平锁**,实现类为: ```java RLock lock = redisson.getFairLock("myLock"); ``` ### 一、什么是公平锁? 公平锁表示: 多个线程在获取锁时,**按照请求锁的先后顺序**来获取锁,先申请锁的线程,先获得锁。 ### 二、Redisson 公平锁的实现原理: Redisson 的公平锁(Fair Lock)底层是基于 **Redis数据结构(ZSet + List)** 实现的,和普通锁(RLock)实现有差异: Redisson 公平锁会用两个关键的 Redis 数据结构: - `List`:**队列**,保存等待中的线程。 - `ZSet`:**有序集合**,保存线程等待锁的时间戳,用于排序,确保先请求锁的线程优先获得锁。 ### 三、具体的实现细节: 当线程请求公平锁时: 1. **尝试获取锁** - 先判断锁是否空闲(Redis中key是否存在)。 - 若锁空闲,且队列中无更早等待的线程,则立即获得锁。 - 若锁已被占用或队列中已有其他等待线程,进入等待队列。 2. **进入等待队列** - 将线程唯一标识放入 Redis 的等待队列(List),同时在 ZSet 中记录线程请求锁的当前时间戳。 - 然后订阅对应的 Redis channel,等待被唤醒。 3. **释放锁** - 当前持锁线程释放锁时,从队列头取出下一个等待线程,并发布消息到 channel,唤醒队首的线程。 ### 四、Redisson 公平锁数据结构举例(伪代码): 例如: ```redis # 公平锁的Key名假设为 myLock myLock:threadQueue (List结构) myLock:timeout (ZSet结构) List: myLock:threadQueue = [threadA_UUID, threadB_UUID, threadC_UUID] ZSet: myLock:timeout = { threadA_UUID : 1700000000001, # 请求时间戳 threadB_UUID : 1700000000100, threadC_UUID : 1700000000200 } ``` - 当锁释放后,Redisson取出`threadQueue`中的第一个元素`threadA_UUID`,唤醒对应线程继续获取锁。 ### 五、公平锁的主要特点: - **避免饥饿现象**:绝对公平,先到先得。 - **性能开销略大**:相比普通锁,需要维护额外的数据结构(ZSet + List),因此性能略低一些。 ### 六、注意事项: - 公平锁适合于明确要求先到先服务的场景(如排队购票、秒杀顺序要求严格的场景)。 - 如果不需要严格的公平性,建议使用性能更高的非公平锁(Redisson默认的`RLock`实现)。 ### 七、示例代码: ```java RLock fairLock = redisson.getFairLock("myFairLock"); try { fairLock.lock(); // 业务逻辑... } finally { fairLock.unlock(); } ``` ### 总结: Redisson的公平锁: - 基于 **Redis的List和ZSet实现**; - 通过队列和时间戳排序,确保公平性; - 会带来一定的性能开销,但能很好地避免饥饿问题; - 不再使用时自动释放资源,业务无需关心底层细节。发布于 2025-03-25 13:48 •IP属地 湖北举报评论收藏
公众号进入网站体验更佳

