文章目錄
- 前話
- 講分布式事務鎖前的幾個概念
- Redis分布式事務鎖原理
- 核心思想
- 問題一
- 問題一
- 問題三
前話
- 大家都知道redis是一個可以高速運行在快取級別的資料庫, 他的高速原因主要有幾個原因
- 絕大部分請求是純粹的記憶體操作(非常快速),避免了與硬碟的接觸
- 豐富的特性:可用于快取,訊息,按key設定過期時間,過期后將會自動洗掉
- 使用大量的hash思想的k v鍵值對, 獲取效率為O(1)
- 依靠非阻塞的IO多路復用原則,使redis形成單執行緒去執行命令的服務器, 避免了不必要的阻塞和背景關系切換和競爭條件
redis采用IO復用實作單執行緒的方式, 將命令任務分裝在佇列中讓一個執行緒去串行化執行, 自然避免了執行緒安全問題, 這也是為什么我們常說redis是基于原子操作的原因
跟多執行緒相比較,執行緒切換需要切換到內核進行執行緒切換,需要消耗時間和資源.而I/O多路復用不需要切換線/行程,效率相對較高,特別是對高并發的應用nginx就是用I/O多路復用,故而性能極佳
- 但是還有一個問題, 上面說redis是單執行緒的, 那么就不會有執行緒安全問題, 那為什么還有讓redis支持事務, 還要 要求他使用redis分布式事務鎖
沒錯,大家所熟知的 Redis 確實是單執行緒模型,指的是執行 Redis 命令的核心模塊是單執行緒的,而不是整個 Redis 實體就一個執行緒,Redis 其他模塊還有各自模塊的執行緒的,
比如socket連接, 這就是一個多執行緒式的
在redis事務中或有一個watch樂觀鎖去監視者資料是否被改動, 如果真的是完全單執行緒, 那么就不需要有這個監視的存在
本質原因就是redis的socket連接是多執行緒的, 我們在開始redis事務, 往里面添加命令其實并沒有真正的執行這些命令, 所以需要watch的監視, 防止其他socket連接進行了資料的操作
下面看看redis的真實運行環境

- 它的組成結構為4部分:多個套接字、IO多路復用程式、檔案事件分派器、事件處理器,
因為檔案事件分派器佇列的消費是單執行緒的,所以Redis才叫單執行緒模型, - 所以Redis 不僅僅是單執行緒, 他需要事務的支持, 就是因為多客戶端對Redis的連接并不存在競爭關系,
- 所以在單機服務器,出現資源的競爭,一般使用synchronized 還可以使用前的redis的事務就可以解決,但是在分布式的服務器上,多個系統或者說多個節點同時訪問你這個redis節點,synchronized 和redis事務就無法解決這個問題,這就需要一個分布式事務鎖,
講分布式事務鎖前的幾個概念
- 分布式:簡單來說就是將業務進行拆分,部署到不同的機器來協調處理,比如用戶在網上買東西,大致分為:訂單系統、庫存系統、支付系統、、、、這些系統共同來完成用戶買東西這個業務操作,
- 集群:同一個業務,通過部署多個實體來完成,保證應用的高可用,如果其中某個實體掛了,業務仍然可以正常進行,通常集群和分布式配合使用,來保證系統的高可用、高性能,
- 分布式事務:按照傳統的系統架構,下單、扣庫存等等,都是在單機系統中, 這一系列的操作都是一個資料庫中完成的,也就是說保證了事務的ACID特性,如果在分布式應用中就會涉及到跨應用、跨庫,這樣就涉及到了分布式事務,就要考慮怎么保證這一系列的操作要么都成功要么都失敗,保證資料的一致性,
- 分布式鎖:因為資源有限,要通過互斥來保持一致性,比如下訂單的資料庫操作和支付的資料庫操作就是一個保證互斥性, 不能同時去執行, 不然那就會出現一旦支付出現失敗, 那么下訂單也得重新下訂單, 這就不合理了, 所以引入分布式事務鎖,
Redis分布式事務鎖原理
- 分布式鎖是控制分布式系統之間同步訪問共享資源的一種方式,如果不同的系統或是同一個系統的不同主機之間共享了一個或一組資源,那么訪問這些資源的時候,往往需要互斥來防止彼此干擾來保證一致性,在這種情況下,便需要使用到分布式鎖,
- 簡單來說就是好幾個節點訪問一個資源, 那我就是使用額外的鎖機制互斥的只讓其中一個能進行訪問
核心思想
- 在被保護的redis節點加一把鎖, 讓這把鎖和被保護的redis節建立直接映射
- 在訪問這個redis之前都去看看這把鎖在不在
- 如果不存在鎖,說明沒有客戶端使用,可以執行任務,執行完畢,解鎖,洗掉鎖 (并且要保證判斷有無鎖和加鎖是原子操作)
- 如果鎖從在則認為有其他客戶端在使用,等待鎖消失

- Redis中可以使用SETNX命令實作分布式鎖,(因redis執行命令是單執行緒所以這個命令是院子的, 完全可以放心去使用),
- SETNX——SET if Not eXists(如果不存在,則設定):
setnx key value
- 如果需要解鎖,使用
del key命令就能釋放鎖
問題一
- 當一個客戶端上鎖之后服務宕機,由于鎖是他上的只有他可以進行redis訪問的,別人無法訪問,所以導致鎖無法被洗掉.
解決思路
- 給鎖設定一個過期時間,可以通過兩種方法實作:通過命令 “setnx 鍵名 過期時間 “;或者通過設定鎖的expire(失效)時間,讓Redis去洗掉鎖,
問題一
- 當一個客戶端設定了鎖的失效時間, 但是這個客戶端并沒有宕機, 只是真的需要那么多時間來進行操作
- 也就是任務執行過長,超過過期時間,
解決思路
這就是上圖那個看門狗的作用可, 這條狗看到時間快到了, 就大喊一聲讓時間倒流~
- 實際是通過客戶端的一個守護執行緒,大概時間快到的時間給執行緒續命.
問題三
- 任務執行造成死回圈,會造成無限續命
解決思路
設定最大續命時間, 或者設定最大續命次數
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/240523.html
標籤:其他
