成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

基于 Redis 如何實現一個分布式鎖?

存儲 存儲軟件 分布式 Redis
與分布式鎖相對應的是「單機鎖」,我們在寫多線程程序時,避免同時操作一個共享變量產生數據問題,通常會使用一把鎖來「互斥」,以保證共享變量的正確性,其使用范圍是在「同一個進程」中。

[[432396]]

一、為什么需要分布式鎖?

在開始講分布式鎖之前,有必要簡單介紹一下,為什么需要分布式鎖?

與分布式鎖相對應的是「單機鎖」,我們在寫多線程程序時,避免同時操作一個共享變量產生數據問題,通常會使用一把鎖來「互斥」,以保證共享變量的正確性,其使用范圍是在「同一個進程」中。

如果換做是多個進程,需要同時操作一個共享資源,如何互斥呢?

例如,現在的業務應用通常都是微服務架構,這也意味著一個應用會部署多個進程,那這多個進程如果需要修改 MySQL 中的同一行記錄時,為了避免操作亂序導致數據錯誤,此時,我們就需要引入「分布式鎖」來解決這個問題了。

想要實現分布式鎖,必須借助一個外部系統,所有進程都去這個系統上申請「加鎖」。

而這個外部系統,必須要實現「互斥」的能力,即兩個請求同時進來,只會給一個進程返回成功,另一個返回失敗(或等待)。

這個外部系統,可以是 MySQL,也可以是 Redis 或 Zookeeper。但為了追求更好的性能,我們通常會選擇使用 Redis 或 Zookeeper 來做。

下面我就以 Redis 為主線,由淺入深,帶你深度剖析一下,分布式鎖的各種「安全性」問題,幫你徹底理解分布式鎖。

二、分布式鎖怎么實現?

我們從最簡單的開始講起。

想要實現分布式鎖,必須要求 Redis 有「互斥」的能力,我們可以使用 SETNX 命令,這個命令表示SET if Not eXists,即如果 key 不存在,才會設置它的值,否則什么也不做。

兩個客戶端進程可以執行這個命令,達到互斥,就可以實現一個分布式鎖。

客戶端 1 申請加鎖,加鎖成功:

  1. 127.0.0.1:6379> SETNX lock 1 
  2. (integer) 1     // 客戶端1,加鎖成功 

客戶端 2 申請加鎖,因為后到達,加鎖失敗:

  1. 127.0.0.1:6379> SETNX lock 1 
  2. (integer) 0     // 客戶端2,加鎖失敗 

此時,加鎖成功的客戶端,就可以去操作「共享資源」,例如,修改 MySQL 的某一行數據,或者調用一個 API 請求。

操作完成后,還要及時釋放鎖,給后來者讓出操作共享資源的機會。如何釋放鎖呢?

也很簡單,直接使用 DEL 命令刪除這個 key 即可:

  1. 127.0.0.1:6379> DEL lock // 釋放鎖 
  2. (integer) 1 

這個邏輯非常簡單,整體的路程就是這樣:

但是,它存在一個很大的問題,當客戶端 1 拿到鎖后,如果發生下面的場景,就會造成「死鎖」:

程序處理業務邏輯異常,沒及時釋放鎖

進程掛了,沒機會釋放鎖

這時,這個客戶端就會一直占用這個鎖,而其它客戶端就「永遠」拿不到這把鎖了。

怎么解決這個問題呢?

三、如何避免死鎖?

我們很容易想到的方案是,在申請鎖時,給這把鎖設置一個「租期」。

在 Redis 中實現時,就是給這個 key 設置一個「過期時間」。這里我們假設,操作共享資源的時間不會超過 10s,那么在加鎖時,給這個 key 設置 10s 過期即可:

  1. 127.0.0.1:6379> SETNX lock 1    // 加鎖 
  2. (integer) 1 
  3. 127.0.0.1:6379> EXPIRE lock 10  // 10s后自動過期 
  4. (integer) 1 

這樣一來,無論客戶端是否異常,這個鎖都可以在 10s 后被「自動釋放」,其它客戶端依舊可以拿到鎖。

疑問臉,但這樣真的沒問題嗎?

還是有問題。

現在的操作,加鎖、設置過期是 2 條命令,有沒有可能只執行了第一條,第二條卻「來不及」執行的情況發生呢?例如:

  • SETNX 執行成功,執行 EXPIRE 時由于網絡問題,執行失敗
  • SETNX 執行成功,Redis 異常宕機,EXPIRE 沒有機會執行
  • SETNX 執行成功,客戶端異常崩潰,EXPIRE 也沒有機會執行

總之,這兩條命令不能保證是原子操作(一起成功),就有潛在的風險導致過期時間設置失敗,依舊發生「死鎖」問題。

那怎么辦呢?

在 Redis 2.6.12 版本之前,我們需要想盡辦法,保證 SETNX 和 EXPIRE 原子性執行,還要考慮各種異常情況如何處理。

但在 Redis 2.6.12 之后,Redis 擴展了 SET 命令的參數,用這一條命令就可以了:

  1. // 一條命令保證原子性執行 
  2. 127.0.0.1:6379> SET lock 1 EX 10 NX 
  3. OK 

 

這樣就解決了死鎖問題,也比較簡單。

 

責任編輯:武曉燕 來源: 架構精進之路
相關推薦

2020-07-30 09:35:09

Redis分布式鎖數據庫

2023-08-21 19:10:34

Redis分布式

2024-07-15 08:25:07

2024-02-19 00:00:00

Redis分布式

2024-10-07 10:07:31

2024-04-01 05:10:00

Redis數據庫分布式鎖

2024-05-08 10:20:00

Redis分布式

2022-04-14 07:56:30

公平鎖Java線程

2022-09-22 13:28:34

Redis分布式鎖

2022-09-29 08:28:57

SpringRedis分布式

2022-01-06 10:58:07

Redis數據分布式鎖

2023-03-06 08:14:48

MySQLRedis場景

2023-09-04 08:45:07

分布式配置中心Zookeeper

2017-04-13 10:51:09

Consul分布式

2019-02-26 09:51:52

分布式鎖RedisZookeeper

2019-06-19 15:40:06

分布式鎖RedisJava

2022-11-11 08:19:03

redis分布式

2022-10-27 10:44:14

分布式Zookeeper

2022-08-11 18:27:50

面試Redis分布式鎖

2024-01-02 13:15:00

分布式鎖RedissonRedis
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 成人福利网| 免费骚视频| 久久精品亚洲国产奇米99 | 国产精品1区2区3区 男女啪啪高潮无遮挡免费动态 | 欧美精品网站 | 精品久久国产 | 全部免费毛片在线播放网站 | 日日夜夜天天 | 中文字幕一区二区三区精彩视频 | 国产一区二区三区四区三区四 | 久草成人 | 中文字幕视频在线看5 | 免费高清成人 | 欧区一欧区二欧区三免费 | 成人三级视频在线观看 | 91久久久久| 91久久夜色 | 红桃成人在线 | 国产欧美精品一区二区 | av色在线 | 亚洲一区二区三区在线播放 | 成人午夜影院 | 欧美精品一区二区三区蜜臀 | 日韩在线观看视频一区 | 国产精品国产精品国产专区不卡 | 羞羞视频一区二区 | 一级高清视频 | 特一级黄色毛片 | 欧美一级黄色免费看 | 国产黄色免费网站 | 四虎网站在线观看 | 亚洲一区在线免费观看 | 国产综合网址 | 在线中文视频 | 精品久久久久久久久久久 | 亚洲一区二区三区久久久 | 欧美三级免费观看 | 在线免费av电影 | 国产精品久久久久久久久久久久冷 | 国产精品99久久久精品免费观看 | 精品亚洲一区二区三区四区五区 |