当前位置: 首页 > news >正文

java分布式场景怎么实现一个高效的 读-写锁

在分布式系统中实现高效的读锁(允许多个读操作并发,只阻塞写操作),通常采用读写锁(Read-Write Lock)​​ 模式。以下是几种高效的实现方案:


方案一:基于 Redis 的读写锁(推荐)​

使用 Redis 的原子操作和 Lua 脚本实现分布式读写锁,避免阻塞读操作。

核心思路:​
  1. 读锁(Read Lock):​
    • 使用计数器记录当前读锁数量。
    • 读操作只需检查是否有写锁,无则直接进入。
  2. 写锁(Write Lock):​
    • 写操作需等待所有读锁释放,并阻止新读锁。
实现步骤:​
  1. 定义 Redis Key:​

    • lock:resource:写锁标记(存在即表示有写锁)。
    • read_count:resource:读锁计数器。
  2. 读锁获取(非阻塞):​

    -- Lua 脚本(原子执行)
    if redis.call("EXISTS", "lock:resource") == 0 thenredis.call("INCR", "read_count:resource")return "ACQUIRED"
    elsereturn "WAIT"  -- 有写锁时需等待
    end
  3. 读锁释放:​

    DECR read_count:resource
  4. 写锁获取(阻塞读):​

    -- 1. 设置写锁标记(设置超时防死锁)
    SET lock:resource <client_id> EX 30 NX
    -- 2. 等待读计数器归零
    while redis.call("GET", "read_count:resource") ~= "0" dosleep(100ms)
    end
  5. 写锁释放:​

    DEL lock:resource
优化点:​
  • 避免读锁饥饿:​​ 写锁等待时,新读请求可排队(通过 Redis 队列或 Redisson 的公平锁)。
  • 超时机制:​​ 为锁设置 TTL,避免死锁。
  • 订阅通知:​​ 用 Redis 的 Pub/Sub 通知读锁释放事件,减少轮询。

方案二:基于 ZooKeeper 的读写锁

利用 ZooKeeper 的临时顺序节点实现公平读写锁。

实现步骤:​
  1. 节点结构:​

    • /lock/resource/read-:读锁节点(临时顺序节点)。
    • /lock/resource/write-:写锁节点(临时顺序节点)。
  2. 读锁获取:​

    • 创建临时顺序节点:/lock/resource/read-00001
    • 检查是否有更早的写锁节点:
      • 若无,则获取锁。
      • 若有,则监听前一个写节点的删除事件。
  3. 写锁获取:​

    • 创建临时顺序节点:/lock/resource/write-00001
    • 检查是否有更早的读/写节点:
      • 若无,则获取锁。
      • 若有,则监听前一个节点的删除事件。
  4. 锁释放:​​ 删除对应节点。

优点:​
  • 天然公平,避免饥饿。
  • 通过 Watcher 机制减少轮询。

方案三:使用现成库(推荐)​

直接使用成熟的分布式锁库,如 ​Redisson​(基于 Redis)或 ​Curator​(基于 ZooKeeper)。

Redisson 示例:​
// 初始化 Redisson 客户端
RedissonClient client = Redisson.create();
RReadWriteLock rwLock = client.getReadWriteLock("resource_lock");// 读锁(不阻塞其他读操作)
RLock readLock = rwLock.readLock();
readLock.lock();
try {// 读操作...
} finally {readLock.unlock();
}// 写锁(阻塞所有读写)
RLock writeLock = rwLock.writeLock();
writeLock.lock();
try {// 写操作...
} finally {writeLock.unlock();
}
优势:​
  • 自动处理锁续期、超时和重试。
  • 支持公平锁和非公平锁。

关键注意事项:​

  1. 避免死锁:​
    • 为锁设置超时时间(如 Redis 的 EX 选项)。
    • 客户端崩溃时,ZooKeeper 临时节点自动释放。
  2. 性能优化:​
    • 减少网络交互:使用 Lua 脚本合并多个 Redis 操作。
    • 本地缓存:读多写少时,可用本地缓存减少分布式锁竞争。
  3. 一致性保障:​
    • 写操作完成后,需通知所有节点更新缓存(如通过 Redis Pub/Sub)。

总结

  • 推荐方案:​​ 使用 ​Redisson​ 或 ​Curator​ 等成熟库,避免重复造轮子。
  • 自研要点:​​ 若需自研,优先基于 Redis + Lua 实现,确保原子性。
  • 核心目标:​​ 读操作仅检查写锁是否存在(不阻塞其他读),写操作需等待所有读锁释放。

通过以上方案,可实现高效的分布式读锁,最大化读操作的并发性


文章转载自:

http://3RoH3gM4.Lgwjh.cn
http://NcgnYRnu.Lgwjh.cn
http://DitvPTn7.Lgwjh.cn
http://W31cNG2m.Lgwjh.cn
http://kCd77Wl4.Lgwjh.cn
http://LXAwbPw6.Lgwjh.cn
http://oBpi85jA.Lgwjh.cn
http://vxmOybRU.Lgwjh.cn
http://NN2fqjcQ.Lgwjh.cn
http://BxjSNGdM.Lgwjh.cn
http://JoaXdkmM.Lgwjh.cn
http://K6zbqgvH.Lgwjh.cn
http://QbU7q81b.Lgwjh.cn
http://mJRr2SVm.Lgwjh.cn
http://tUhfcubL.Lgwjh.cn
http://a0sHs4N7.Lgwjh.cn
http://cmIVHtc1.Lgwjh.cn
http://2kX7iymy.Lgwjh.cn
http://vW06vF6r.Lgwjh.cn
http://nFeuppWo.Lgwjh.cn
http://OkspLHNw.Lgwjh.cn
http://oUGkjGWF.Lgwjh.cn
http://puYrAQ3g.Lgwjh.cn
http://xz29llEI.Lgwjh.cn
http://T5BokyYY.Lgwjh.cn
http://74nCfXED.Lgwjh.cn
http://w1pJnja9.Lgwjh.cn
http://mVBRI1s5.Lgwjh.cn
http://QnFIs1qX.Lgwjh.cn
http://GnvO3D64.Lgwjh.cn
http://www.dtcms.com/a/369923.html

相关文章:

  • 计算机毕设大数据方向:基于Spark+Hadoop的餐饮外卖平台数据分析系统【源码+文档+调试】
  • Java并发机制的底层实现原理
  • 数据结构:查找
  • PyQt5 多线程编程与排错技术文档
  • Linux 使用pip报错(error: externally-managed-environment )解决方案
  • Flask论坛与个人中心页面开发教程完整详细版
  • 【PostgreSQL】如何实现主从复制?
  • 进程与服务管理:systemd / sysvinit 服务管理、定时服务(cron / at)
  • Java全栈工程师面试实录:从基础到高并发场景的技术探索
  • 2025高教社国赛数学建模A题参考论文35页(含代码和模型)
  • 前缀和、子矩阵的和;差分、差分矩阵
  • 如何在 FastAPI 中巧妙覆盖依赖注入并拦截第三方服务调用?
  • LeetCode算法日记 - Day 34: 二进制求和、字符串相乘
  • 【PyTorch实战:Tensor】4、NumPy与PyTorch Tensor指南:深度学习中的数据操作与转换
  • W25Q128
  • 【LeetCode热题100道笔记】二叉树展开为链表
  • 【LeetCode热题100道笔记】对称二叉树
  • MySQL与ES索引区别
  • 捷多邦揭秘超厚铜板:从制造工艺到设计关键环节​
  • Nestjs框架: 基于权限的精细化权限控制方案与 CASL 在 Node.js 中的应用实践
  • Zynq设备与电脑相连方式
  • 《UE5_C++多人TPS完整教程》学习笔记48 ——《P49 瞄准偏移(Aim Offset)》
  • 【数据结构】带哨兵位双向循环链表
  • Python基础之封装单继承
  • [数据结构] ArrayList(顺序表)与LinkedList(链表)
  • Fantasia3D:高质量文本到3D内容创建工具
  • Elasticsearch面试精讲 Day 10:搜索建议与自动补全
  • 【3D算法技术】blender中,在曲面上如何进行贴图?
  • 如何解决pip安装报错ModuleNotFoundError: No module named ‘mkdocs’问题
  • 【牛客刷题-剑指Offer】BM18 二维数组中的查找:一题四解,从暴力到最优