現(xiàn):從原理到實(shí)戰(zhàn))
1. 引言在分布式系統(tǒng)中多個(gè)服務(wù)實(shí)例可能同時(shí)操作共享資源如果缺乏互斥機(jī)制就會(huì)出現(xiàn)超賣、重復(fù)扣款、數(shù)據(jù)覆蓋等問(wèn)題。分布式鎖正是為了解決這類跨進(jìn)程、跨節(jié)點(diǎn)的并發(fā)競(jìng)爭(zhēng)問(wèn)題而設(shè)計(jì)的通用方案。本文圍繞分布式鎖的核心原理給出基于 Redis 的完整代碼實(shí)現(xiàn)并討論常見(jiàn)注意事項(xiàng)。2. 核心原理分布式鎖的本質(zhì)是讓多個(gè)進(jìn)程在共享存儲(chǔ)上競(jìng)爭(zhēng)一個(gè)「唯一標(biāo)記」誰(shuí)拿到標(biāo)記誰(shuí)就獲得執(zhí)行權(quán)。以 Redis 為例最樸素的做法是利用SETNX命令只有當(dāng) key 不存在時(shí)才能寫(xiě)入成功寫(xiě)入成功的節(jié)點(diǎn)即獲得鎖。為了避免死鎖鎖必須設(shè)置過(guò)期時(shí)間為了避免誤刪他人鎖釋放前要校驗(yàn)持有者標(biāo)識(shí)。3. 代碼實(shí)現(xiàn)下面給出一個(gè)基于 Redis 的分布式鎖實(shí)現(xiàn)使用 Java 語(yǔ)言和 Jedis 客戶端代碼可直接復(fù)制運(yùn)行。import redis.clients.jedis.Jedis; import java.util.UUID; public class RedisLock { private Jedis jedis; private String lockKey; private String requestId; private int expireTime 30000; // 鎖自動(dòng)過(guò)期時(shí)間單位毫秒 public RedisLock(Jedis jedis, String lockKey) { this.jedis jedis; this.lockKey lockKey; this.requestId UUID.randomUUID().toString(); } // 加鎖SETNX 過(guò)期時(shí)間保證原子性 public boolean tryLock() { String result jedis.set(lockKey, requestId, NX, PX, expireTime); return OK.equals(result); } // 解鎖先校驗(yàn)持有者再刪除防止誤刪他人鎖 public void unlock() { String script if redis.call(get, KEYS[1]) ARGV[1] then return redis.call(del, KEYS[1]) else return 0 end; jedis.eval(script, 1, lockKey, requestId); } }使用示例Jedis jedis new Jedis(localhost, 6379); RedisLock lock new RedisLock(jedis, order:12345); if (lock.tryLock()) { try { // 執(zhí)行臨界區(qū)業(yè)務(wù)邏輯 System.out.println(獲取鎖成功執(zhí)行業(yè)務(wù)); } finally { lock.unlock(); } } else { System.out.println(獲取鎖失敗稍后重試); }4. 注意事項(xiàng)第一加鎖和解鎖必須保證原子性避免「先 SETNX 再單獨(dú) EXPIRE」這種非原子寫(xiě)法。第二釋放鎖前必須校驗(yàn)持有者標(biāo)識(shí)否則可能誤刪其他線程的鎖。第三業(yè)務(wù)執(zhí)行時(shí)間不能超過(guò)鎖的過(guò)期時(shí)間否則鎖提前失效會(huì)導(dǎo)致并發(fā)問(wèn)題必要時(shí)可引入看門狗續(xù)期機(jī)制。第四在 Redis 主從架構(gòu)下主節(jié)點(diǎn)宕機(jī)可能導(dǎo)致鎖丟失對(duì)強(qiáng)一致性要求高的場(chǎng)景可考慮 Redlock 算法。5. 總結(jié)分布式鎖是解決分布式并發(fā)競(jìng)爭(zhēng)的基礎(chǔ)組件。本文給出的 Redis 實(shí)現(xiàn)覆蓋了加鎖、解鎖和防誤刪三個(gè)關(guān)鍵環(huán)節(jié)代碼簡(jiǎn)潔且可直接落地。實(shí)際生產(chǎn)環(huán)境中建議優(yōu)先使用 Redisson 等成熟客戶端它們內(nèi)置了看門狗續(xù)期和 Redlock 支持能進(jìn)一步降低實(shí)現(xiàn)復(fù)雜度。