
分布式锁JVM内锁只能同时锁住同一个JVM内线程;而分布式场景下多服务实例需要跨进程、跨节点互斥就是分布式锁。一、Redis实现方案1SETNXEXPIRE;方案2set命令原子加过期// SET key value NX EX 30 原子命令 Boolean ok redisTemplate.opsForValue().setIfAbsent(lock:order:1001, uuid, 30, TimeUnit.SECONDS); if (ok) { try { // 业务逻辑 } finally { // 释放锁必须校验持有者防止删别人的锁 String script if redis.call(get,KEYS[1]) ARGV[1] then return redis.call(del,KEYS[1]) else return 0 end ; redisTemplate.execute(new DefaultRedisScript(script, Long.class), List.of(lock:order:1001), uuid); } }方案3RedissonRedisson的底层就是Redis具有 自动续期看门狗机制可重入锁公平锁、读写锁、锁超时、lua脚本。RLock lock redissonClient.getLock(lock:order:1001); try { // tryLock(等待时间, 锁持有时间, 时间单位) boolean acquire lock.tryLock(10, 30, TimeUnit.SECONDS); if (acquire) { // 业务代码 } } finally { if (lock.isHeldByCurrentThread()) { lock.unlock(); } }如果不指定leaseTimeRedisson默认30s后端线程每10s续期业务没跑完不会自动释放。二、Zookeeper实现分布式锁利用zk临时有序节点 Watcher1.抢锁在/lock/order下创建临时有序节点lock-000000012.判断自己是不是最小节点-拿到锁3.不是最小节点监听前一个节点等待释放通知4.断开连接临时节点自动删除不会死锁优点是天然支持监听不会死锁缺点是zk性能比较弱适合并发不高的场景。InterProcessMutex lock new InterProcessMutex(client, /lock/order); try { if (lock.acquire(10, TimeUnit.SECONDS)) { // 业务 } } finally { lock.release(); }三、数据库实现分布式锁乐观锁/悲观锁悲观锁select ... for update-- 注意必须索引命中否则会表锁InnoDB事务内生效 select * from distribute_lock where lock_key order:1001 for update;局限如下必须事务集群下数据库单点问题长时间不提交事务会连接占用只适合低并发乐观锁版本号机制无阻塞update goods set stock stock -1, version version 1 where id1 and version #{oldVersion};根据update返回行数判断是否抢到锁没有阻塞失败直接充实适合读多写少。