Redis(七)分布式鎖

來源:互聯網
上載者:User

標籤:tps   綁定   死結   組織   代碼   訪問共用   沒有   ali   特殊   

前面學習了Redis的資料結構以及命令、Redis中的事務和Redis對Lua指令碼的支援。

這一章就對Redis這些特性做一下實戰性應用——基於Redis的分布式鎖實現。

Lock和Distributed Lock

在這之前先來認識下鎖(Lock)和分布式鎖(Distributed Lock):

In computer science, a lock or mutex (from mutual exclusion) is a synchronization mechanism for enforcing limits on access to a resource in an environment where there are many threads of execution. A lock is designed to enforce a mutual exclusion concurrency control policy.

參考wiki的解釋:在電腦科學領域中,鎖是為了限制多線程環境訪問一個資源的一種同步機制。鎖被設計相互排斥的並發策略。

Lock的前提條件:

  • 同一台機器上的共同資源;
  • 多線程環境訪問共同資源;

Lock目標:

  • 保證多線程訪問資源的一致性;

Lock的實現:

  • 單核處理器上禁用中斷,使得同步資源能夠被訪問結束;
  • 硬體支援的原子指令,“比較和交換”等等,用於測試鎖是否是空閑,如果空閑擷取鎖;

Operating systems use lock managers to organise and serialise the access to resources. A distributed lock manager (DLM) runs in every machine in a cluster, with an identical copy of a cluster-wide lock database. In this way a DLM provides software applications which are distributed across a cluster on multiple machines with a means to synchronize their accesses to shared resources.

參考wiki解釋分布式鎖:作業系統用鎖管理器實現有組織有順序的訪問資源。分布式鎖運行在叢集環境中的每台機器上,使得資料具有相同的副本。分布式鎖提供分布式軟體應用同步訪問共用資源。

Distribute Lock的前提條件:

  • 分布式軟體應用;
  • 分布式軟體中的共用資源;

Distribute Lock目標:

  • 保證分布式應用訪問共用資源的一致性

Distribute Lock實現方式:

  • 基於Redis實現;
  • 基於Zookeeper實現;
  • 基於Etcd或者Consul實現;
  • Google開發的Chubby(Lock Service);
獨佔式鎖的特點和影響

按照用途、情境劃分,鎖的類型非常多。如:排它鎖(獨佔式鎖)、共用鎖定,自旋鎖、互斥鎖,讀鎖、寫鎖。但是在分布式環境中的所謂的分布式鎖,大多數情況下都是指:分布式獨佔式鎖。

1.特點分析:

  • 每次只能一個佔用鎖;
  • 可以重複進入鎖;
  • 只有佔用者才可以解鎖;
  • 擷取鎖和釋放鎖都需要原子
  • 不能產生死結
  • 盡量滿足效能

本質:同步互斥,使得處理任務能夠一個一個逐步的過臨界資源。

造成的影響:

  • 降低並發數,使得多任務處理,只能一個一個的進行;
  • 任務的換進換出造成切換上的開銷;

本質:使得輸送量大打折扣。

基於Redis的實現Redis實現分布式鎖的基礎

1.Redis本身就是單線程:

  • 單個命令執行具有原子性、無競態條件,這個特點符合一次只有一個用戶端爭用鎖;

2.Redis提供了set if not exists操作:

  • 存在即不設定,這個特點符合鎖的獨佔性(排它特點);

下面來先來看下擷取鎖:

return jedis.set(lockKey, lockValue, NX, EX, expireTime) != null ? true : false;

這裡使用set指令,具有原子操作特點,不會被其他用戶端操作中斷,在分布式環境中,是安全的,沒有競態條件產生,一次只能有一個用戶端爭用鎖;使用nx,即存在不設定,符合獨佔特點;設定ex,有到期效果,不會產生永久獨佔即死結;最後設定了lockValue,這樣就和當前加鎖任務做了綁定,後面可以用其作為解鎖的鑰匙;

再來看下解鎖操作:

static final String RELEASE_LOCK_LUA = "if redis.call(‘get‘, KEYS[1]) == ARGV[1] " +            "then return redis.call(‘del‘, KEYS[1]) else return 0 end";            Object result = jedis.eval(RELEASE_LOCK_LUA, 1, lockKey, lockValue);

這裡解鎖是用了Lua指令碼,上篇文章中介紹了Redis內建一個Lua解譯器,Redis調用解譯器執行Lua指令碼也是具有原子性的,即同一時刻只有一個用戶端的操作能被執行,所以這裡使用Lua指令碼解鎖無競態條件;解鎖符合是佔用鎖的任務釋放的原理;

但是以上實現的分布式鎖缺點是:

  • 不具有重入性,即當前任務擷取了鎖,在下次擷取時將會死結;
  • 不能自旋擷取,即擷取失敗時,將會立即返回失敗;

本人對其進行了改造,分別做了適應以上兩種情境的分布式鎖,詳情可以戮[Distributed Lock],歡迎大家一起來完善。

總結

本文從What、Features、How的角度分析了分布式鎖。總的來說,單機應用中的多線程或者多進程的鎖的放大版基本上就是分布式鎖了。萬變不離其宗,實現獨佔鎖的關鍵性要素:

  • 目標:互斥同步,資源訪問原子化;
  • 實現:一次只能有一個爭用到鎖,爭用過程是個原子過程,只能爭用到的解鎖,不會發生死結;
參考

Redis 分布式鎖的正確實現方式
Rewriting our lock
Lock

題外話

參考Rewriting our lock中使用setnx實現的分布式,嚴格意義上來說是有死結問題的。setnx和expire不具有原子性。當setnx成功後,expire前應用發生宕機,這會導致鎖永遠不會到期,別的應用始終爭用不到鎖。當然這種情況比較特殊,但是做代碼是一件嚴謹的事!

Redis(七)分布式鎖

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.