ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Redisson 分布式锁怎么选:RLock、FairLock、MultiLock 与 SpinLock 的取舍

Redisson 分布式锁怎么选:RLock、FairLock、MultiLock 与 SpinLock 的取舍 Redisson 分布式锁怎么选RLock、FairLock、MultiLock 与 SpinLock 的取舍【免费下载链接】redissonRedisson: Valkey Redis Java Client and Real-Time Data Platform. Sync/Async/RxJava/Reactive API. Over 50 Valkey and Redis based Java objects and services: Set, Multimap, SortedSet, Map, List, Queue, Deque, Semaphore, Lock, AtomicLong, Map Reduce, Bloom filter, Spring, Tomcat, Scheduler, JCache API, Hibernate, RPC, local cache..项目地址: https://gitcode.com/GitHub_Trending/re/redisson在 Java 应用里用 Redisson 给一段业务逻辑加分布式锁时第一步不是写代码而是选对锁类型。Redisson 提供的Lock、Fair Lock、MultiLock、Spin Lock共享同一套RLock风格 API 和 watchdog 续期机制但它们在授予顺序、是否能合并多把锁、等待线程如何被通知这三点上行为不同选错会直接表现为公平性不符合预期或pub/sub 消息量打爆集群。本文基于 锁与同步器文档 给出选择依据和四种锁的最小可用代码适用环境是已能连接 Valkey 或 Redis 的 Java 项目。先看判断维度Redisson 官方给出的取舍表Choosing a lock 一节的官方对照表✔️/❌ 整理为是/否锁类型可重入公平 / FIFOFencing token等待机制典型用途LockRLock是否否Pub/sub通用互斥Non-Reentrant Lock否否否Pub/sub同一线程必须不可重入的互斥Fair Lock是是否Pub/sub授予必须按请求顺序FIFONon-Reentrant Fair Lock否是否Pub/sub需要 FIFO 但不可重入MultiLock是否否Pub/sub把多把锁作为一个整体获取ReadWriteLock是否否Pub/sub多读者并发、单一写者Spin Lock是否否退避轮询锁数量极大每把锁一个 pub/sub 订阅代价太高Fenced Lock是否是Pub/sub保护外部资源防过期持锁者写入选型可以压缩成三个问题是否要求先来后到是 → Fair Lock否 → 继续看下一问。是否要把多个 key / 多个 Redisson 实例上的锁当一个锁获取是 → MultiLock。锁的数量是否达到短时间大量获取/释放的量级是 → Spin Lock否 → 默认的RLock。这四种锁有几个共同行为选完类型后都要遵守watchdog 自动续期持锁方 Redisson 实例崩溃时锁理论上可能永远停留在已获取状态。watchdog 在持锁方存活期间不断延长锁过期时间默认超时 30 秒可通过 Config.lockWatchdogTimeout默认值30000毫秒修改。该参数只在未指定leaseTime获取锁时生效。leaseTime自动释放获取时可传入leaseTime例如lock.lock(10, TimeUnit.SECONDS)到期后锁自动释放。只有持有线程能释放非持锁线程调用unlock()会抛IllegalMonitorStateException文档同时建议若需要任意线程释放应考虑用RSemaphore。异步 API 要固定 threadId在 Async、Reactive、RxJava3 API 中一次逻辑操作可能跨多个线程执行而锁所有权绑定 thread id。文档要求捕获Thread.currentThread().getId()并把同一个threadId传入lock、tryLock和unlock调用。准备条件创建 Redisson 客户端按 Getting Started 的两步走。先加依赖社区版坐标如下xVERSIONx是文档中的模板变量替换为你实际采用的版本dependency groupIdorg.redisson/groupId artifactIdredisson/artifactId versionxVERSIONx/version /dependency再创建客户端。连接模式single / replicated / cluster / sentinel 等见 配置文档单机模式示例地址按实际部署替换Config config new Config(); config.useSingleServer().setAddress(redis://127.0.0.1:6379); // Sync and Async API RedissonClient redisson Redisson.create(config);RedissonClient是线程安全的文档建议只创建一个实例并在应用内复用应用停止时调用redisson.shutdown()。通用互斥RLockRLock是基础选项可重入的分布式Lock实现java.util.concurrent.locks.Lock接口通过 pub/sub 通道跨所有 Redisson 实例通知等待线程。RLock lock redisson.getLock(myLock); // myLock 为锁名称按业务命名 // 传统阻塞式获取 lock.lock(); // 或获取后 10 秒自动释放 lock.lock(10, TimeUnit.SECONDS); // 或最多等 100 秒获取成功后 10 秒自动释放 boolean res lock.tryLock(100, 10, TimeUnit.SECONDS); if (res) { try { // 临界区 } finally { lock.unlock(); } }tryLock的返回值res就是最直接的结果判断true表示在等待窗口内拿到了锁false表示没有。如果业务要求持锁线程绝不允许再次加锁用来尽早暴露编程错误可改用非可重入变体redisson.getNonReentrantLock(myLock)同一线程无论通过lock()、tryLock()还是tryLock(waitTime, unit)再次获取都会立即抛IllegalMonitorStateException其他线程照常竞争。按请求顺序授予锁FairLockFair Lock是可重入的公平锁保证线程按请求顺序获取锁所有等待线程排队。注意它有一个文档明确给出的代价——如果某个等待线程死亡Redisson 会等它返回 5 秒例如 5 个线程因故死亡则延迟 25 秒文档示例。对等待时延敏感的公平性场景要评估这一点。RLock lock redisson.getFairLock(myLock); lock.lock(); // 或获取后 10 秒自动释放 lock.lock(10, TimeUnit.SECONDS); // 或最多等 100 秒获取成功后 10 秒自动释放 boolean res lock.tryLock(100, 10, TimeUnit.SECONDS); if (res) { try { // 临界区 } finally { lock.unlock(); } }获取方式与普通RLock的差别只在getFairLock(...)这一个入口其余lock/tryLock/unlock用法一致。把多把锁当一个锁MultiLockMultiLock用于把多个RLock对象分组、作为一把锁来处理。关键点是每个RLock可以属于不同的 Redisson 实例——即锁分布在不同服务端时也能合并。文档示例中的redisson1/redisson2/redisson3即代表三个实例的客户端anyRedisson是任意一个可用实例RLock lock1 redisson1.getLock(lock1); RLock lock2 redisson2.getLock(lock2); RLock lock3 redisson3.getLock(lock3); RLock multiLock anyRedisson.getMultiLock(lock1, lock2, lock3); // 传统阻塞式获取等价于同时拿到 lock1、lock2、lock3 multiLock.lock(); // 或获取后 10 秒自动释放 multiLock.lock(10, TimeUnit.SECONDS); // 或最多等 100 秒获取成功后 10 秒自动释放 boolean res multiLock.tryLock(100, 10, TimeUnit.SECONDS); if (res) { try { // 临界区此时三把锁都已持有 } finally { multiLock.unlock(); } }MultiLock同样是可重入的且只有持锁线程能unlock()规则与RLock一致。海量短促锁SpinLockLock对象依赖 pub/sub 通知等待线程而 pub/sub 消息会分发到集群所有节点。文档明确指出如果短时间内有大量锁的获取/释放可能触及网络吞吐上限并造成 Valkey 或 Redis 的 CPU 过载。Spin Lock就是针对这个场景的它默认用Exponential Backoff指数退避轮询替代 pub/sub 通道来获取锁。RLock lock redisson.getSpinLock(myLock); lock.lock(); // 或获取后 10 秒自动释放 lock.lock(10, TimeUnit.SECONDS); // 或最多等 100 秒获取成功后 10 秒自动释放 boolean res lock.tryLock(100, 10, TimeUnit.SECONDS); if (res) { try { // 临界区 } finally { lock.unlock(); } }API 形态与RLock完全一致切换成本只是把getLock换成getSpinLock。选择依据就是上文一句话锁数量极大、且每把锁的 pub/sub 订阅代价高时用它普通业务互斥不需要。安全边界watchdog 与从库同步检查选完锁类型之后还有两个与锁会不会失效直接相关的配置全部类型适用。从库同步检查默认开启获取RLock是往主节点写锁记录若主节点在记录复制到从节点前故障转移新主节点上没有这把锁另一个客户端就能再次获取出现两个客户端各自认为自己持锁。Redisson 的对策是获取后校验锁已传播到已连接的从节点由两个 Config 项控制checkLockSyncedSlaves— 是否在获取后确认锁到达已连接的从节点默认开启默认值trueslavesSyncTimeout— 等待该同步的毫秒数默认1000同一超时应用于RLock、RSemaphore、RPermitExpirableSemaphore。Config config new Config(); config.setCheckLockSyncedSlaves(true) // default .setSlavesSyncTimeout(1000); // milliseconds, default开启检查时若所需从节点在slavesSyncTimeout内未确认同步Redisson 会释放锁并让本次获取失败——客户端不会长期持有把一把未来可能被 failover 丢掉的锁。watchdog 续期默认 30 秒超时lockWatchdogTimeout默认30000毫秒只在未指定leaseTime获取锁时生效它防止持锁方崩溃导致锁无限期挂起。验证锁是否按预期工作文档给出的行为判断点可用于上线前核对实现是否符合预期获取结果tryLock(waitTime, leaseTime, unit)返回true/false为false说明等待窗口内未获得锁。持有权检查非持锁线程调用unlock()会抛IllegalMonitorStateException。如果测试中它意外抛出说明业务里存在跨线程释放锁的调用路径。从库同步失败在checkLockSyncedSlaves开启且从节点未能在slavesSyncTimeout内确认时获取会失败锁被释放。集群从节点异常期间如果出现获取失败先核对该配置与从节点状态。公平性Fair Lock下等待线程严格按请求顺序进入临界区若观察到乱序需确认拿到的是getFairLock而非getLock。非可重入变体getNonReentrantLock/getNonReentrantFairLock下同一线程第二次加锁立即抛IllegalMonitorStateException——这是文档描述的预期行为用于暴露本不应重入的代码路径。什么时候该用本文四种之外的类型多读单写ReadWriteLockredisson.getReadWriteLock(myLock)允许多个 ReadLock 持有者和一个 WriteLock 持有者读/写锁各自实现RLock接口。锁保护外部系统写入RFencedLock在每次获取时返回单调递增的 fencing tokenlockAndGetToken()获取并返回 tokengetToken()不获取锁直接取当前值tryLockAndGetToken(...)未获取成功时返回null被保护的资源记录见过的最高 token 并拒绝更低的 token。锁守护的写入方可以校验 token 时才选它纯进程内/分布式互斥用RLock即可。RedLock 已废弃文档明确标注RedLockdeprecated由RLock 从库同步检查以及需要 token 时的RFencedLock取代新项目不应再引入。选型落点默认用RLock有顺序要求换getFairLock跨实例合并多把锁用getMultiLock海量短促锁用getSpinLock。四种锁共用 watchdog、leaseTime与仅持锁线程可释放规则配置上默认已开启从库同步检查核对上面第 1、2、3 条行为后即可按各自业务验证临界区逻辑。【免费下载链接】redissonRedisson: Valkey Redis Java Client and Real-Time Data Platform. Sync/Async/RxJava/Reactive API. Over 50 Valkey and Redis based Java objects and services: Set, Multimap, SortedSet, Map, List, Queue, Deque, Semaphore, Lock, AtomicLong, Map Reduce, Bloom filter, Spring, Tomcat, Scheduler, JCache API, Hibernate, RPC, local cache..项目地址: https://gitcode.com/GitHub_Trending/re/redisson创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表