您好,登錄后才能下訂單哦!
這篇文章主要介紹“如何通過Redis實現分布式鎖”,在日常操作中,相信很多人在如何通過Redis實現分布式鎖問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”如何通過Redis實現分布式鎖”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
常用的 SQL 數據庫的數據都是存在磁盤中的,雖然在數據庫底層也做了對應的緩存來減少數據庫的 IO 壓力。
由于數據庫的緩存一般是針對查詢的內容,而且粒度也比較小,一般只有表中的數據沒有發生變動的時候,數據庫的緩存才會產生作用。但這并不能減少業務邏輯對數據庫的增刪改操作的 IO 壓力,因此緩存技術應運而生,該技術實現了對熱點數據的高速緩存,可以大大緩解后端數據庫的壓力。
1、主流應用架構:
客戶端在對數據庫發起請求時,先到緩存層查看是否有所需的數據,如果緩存層存有客戶端所需的數據,則直接從緩存層返回,否則進行穿透查詢,對數據庫進行查詢。如果在數據庫中查詢到該數據,則將該數據回寫到緩存層,以便下次客戶端再次查詢能夠直接從緩存層獲取數據。
2、為什么 Redis 能這么快
Redis 的效率很高,官方給出的數據是 100000+QPS,這是因為:Redis 完全基于內存,絕大部分請求是純粹的內存操作,執行效率高。Redis 使用單進程單線程模型的(K,V)數據庫,將數據存儲在內存中,存取均不會受到硬盤 IO 的限制,因此其執行速度極快。另外單線程也能處理高并發請求,還可以避免頻繁上下文切換和鎖的競爭,如果想要多核運行也可以啟動多個實例。
數據結構簡單,對數據操作也簡單,Redis 不使用表,不會強制用戶對各個關系進行關聯,不會有復雜的關系限制,其存儲結構就是鍵值對,類似于 HashMap,HashMap 最大的優點就是存取的時間復雜度為 O(1)。
Redis 使用多路 I/O 復用模型,為非阻塞 IO。注:Redis 采用的 I/O 多路復用函數:epoll/kqueue/evport/select。
選用策略:
因地制宜,優先選擇時間復雜度為 O(1) 的 I/O 多路復用函數作為底層實現。由于 Select 要遍歷每一個 IO,所以其時間復雜度為 O(n),通常被作為保底方案。基于 React 設計模式監聽 I/O 事件。
3、Redis 的數據類型
String:最基本的數據類型,其值最大可存儲 512M,二進制安全(Redis 的 String 可以包含任何二進制數據,包含 jpg 對象等)。注:如果重復寫入 key 相同的鍵值對,后寫入的會將之前寫入的覆蓋。
Hash:String 元素組成的字典,適用于存儲對象。
List:列表,按照 String 元素插入順序排序。其順序為后進先出。由于其具有棧的特性,所以可以實現如“最新消息排行榜”這類的功能。
Set:String 元素組成的無序集合,通過哈希表實現(增刪改查時間復雜度為 O(1)),不允許重復。另外,當我們使用 Smembers 遍歷 Set 中的元素時,其順序也是不確定的,是通過 Hash 運算過后的結果。Redis 還對集合提供了求交集、并集、差集等操作,可以實現如同共同關注,共同好友等功能。
Sorted Set:通過分數來為集合中的成員進行從小到大的排序。
更高級的Redis類型:用于計數的HyperLogLog、用于支持存儲地理位置信息的 Geo。
4、如何通過 Redis 實現分布式鎖
分布式鎖:分布式鎖是控制分布式系統之間共同訪問共享資源的一種鎖的實現。如果一個系統,或者不同系統的不同主機之間共享某個資源時,往往需要互斥,來排除干擾,滿足數據一致性。
分布式鎖需要解決的問題如下:
互斥性:任意時刻只有一個客戶端獲取到鎖,不能有兩個客戶端同時獲取到鎖。
安全性:鎖只能被持有該鎖的客戶端刪除,不能由其他客戶端刪除。
死鎖:獲取鎖的客戶端因為某些原因而宕機繼而無法釋放鎖,其他客戶端再也無法獲取鎖而導致死鎖,此時需要有特殊機制來避免死鎖。
容錯:當各個節點,如某個 Redis 節點宕機的時候,客戶端仍然能夠獲取鎖或釋放鎖。
5、如何實現異步隊列
(1)使用 Redis 中的 List 作為隊列
使用上文所說的 Redis 的數據結構中的 List 作為隊列 Rpush 生產消息,LPOP 消費消息。此時我們可以看到,該隊列是使用 Rpush 生產隊列,使用 LPOP 消費隊列。在這個生產者-消費者隊列里,當 LPOP 沒有消息時,證明該隊列中沒有元素,并且生產者還沒有來得及生產新的數據。
缺點:LPOP 不會等待隊列中有值之后再消費,而是直接進行消費。
彌補:可以通過在應用層引入 Sleep 機制去調用 LPOP 重試。
(2)使用 BLPOP key [key…] timeout
BLPOP key [key …] timeout:阻塞直到隊列有消息或者超時。
缺點:按照此種方法,我們生產后的數據只能提供給各個單一消費者消費。能否實現生產一次就能讓多個消費者消費呢?
(3)Pub/Sub:主題訂閱者模式
發送者(Pub)發送消息,訂閱者(Sub)接收消息。訂閱者可以訂閱任意數量的頻道。Pub/Sub模式的缺點:消息的發布是無狀態的,無法保證可達。對于發布者來說,消息是“即發即失”的。此時如果某個消費者在生產者發布消息時下線,重新上線之后,是無法接收該消息的,要解決該問題需要使用專業的消息隊列,如 Kafka…此處不再贅述。
6、Redis 持久化
(1)什么是持久化?
持久化,即將數據持久存儲,而不因斷電或其他各種復雜外部環境影響數據的完整性。由于 Redis 將數據存儲在內存而不是磁盤中,所以內存一旦斷電,Redis 中存儲的數據也隨即消失,這往往是用戶不期望的,所以 Redis 有持久化機制來保證數據的安全性。
(2)Redis 如何做持久化
Redis 目前有兩種持久化方式,即 RDB 和 AOF,RDB 是通過保存某個時間點的全量數據快照實現數據的持久化,當恢復數據時,直接通過 RDB 文件中的快照,將數據恢復。如何從海量數據里快速找到所需?
①分片:按照某種規則去劃分數據,分散存儲在多個節點上。通過將數據分到多個 Redis 服務器上,來減輕單個 Redis 服務器的壓力。
②一致性 Hash 算法:既然要將數據進行分片,那么通常的做法就是獲取節點的 Hash 值,然后根據節點數求模。但這樣的方法有明顯的弊端,當 Redis 節點數需要動態增加或減少的時候,會造成大量的 Key 無法被命中。所以 Redis 中引入了一致性 Hash 算法。該算法對 2^32 取模,將 Hash 值空間組成虛擬的圓環,整個圓環按順時針方向組織,每個節點依次為 0、1、2…2^32-1。
之后將每個服務器進行 Hash 運算,確定服務器在這個 Hash 環上的地址,確定了服務器地址后,對數據使用同樣的 Hash 算法,將數據定位到特定的 Redis 服務器上。如果定位到的地方沒有 Redis 服務器實例,則繼續順時針尋找,找到的第一臺服務器即該數據最終的服務器位置。
③Hash 環的數據傾斜問題
Hash 環在服務器節點很少的時候,容易遇到服務器節點不均勻的問題,這會造成數據傾斜,數據傾斜指的是被緩存的對象大部分集中在 Redis 集群的其中一臺或幾臺服務器上。一致性 Hash 算法運算后的數據大部分被存放在 A 節點上,而 B 節點只存放了少量的數據,久而久之 A 節點將被撐爆。針對這一問題,可以引入虛擬節點解決。簡單地說,就是為每一個服務器節點計算多個 Hash,每個計算結果位置都放置一個此服務器節點,稱為虛擬節點,可以在服務器 IP 或者主機名后放置一個編號實現。
到此,關于“如何通過Redis實現分布式鎖”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。