自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

還不知道 Redis 分布式鎖的背后原理?還不趕快學(xué)習(xí)一下

存儲(chǔ) 分布式 Redis
以前在學(xué)校做小項(xiàng)目的時(shí)候,用到Redis,基本也只是用來當(dāng)作緩存??砂⒎墼诠ぷ髦邪l(fā)現(xiàn),Redis在生產(chǎn)中并不只是當(dāng)作緩存這么簡單。

 [[321595]]

以前在學(xué)校做小項(xiàng)目的時(shí)候,用到Redis,基本也只是用來當(dāng)作緩存。可阿粉在工作中發(fā)現(xiàn),Redis在生產(chǎn)中并不只是當(dāng)作緩存這么簡單。在阿粉接觸到的項(xiàng)目中,Redis起到了一個(gè)分布式鎖的作用,具體情況是這樣的:

該項(xiàng)目在某金融平臺(tái)中負(fù)責(zé)某塊業(yè)務(wù),是一個(gè)分布式系統(tǒng),線上大概跑著10個(gè)左右的實(shí)例。其中有一個(gè)步驟需要用戶支付一定的費(fèi)用,Redis分布式鎖在其中大概處于這么一個(gè)位置:

 

可以看到在上分布式鎖之后,系統(tǒng)做了兩個(gè)查詢校驗(yàn),然后向數(shù)據(jù)庫中插入了一條訂單記錄,接著才解鎖進(jìn)入支付流程。

從業(yè)務(wù)的角度考慮分布式鎖是好理解的,它保證了查詢及插入數(shù)據(jù)整個(gè)流程的原子性,防止查詢校驗(yàn)的時(shí)候查到臟數(shù)據(jù),使得支付前訂單信息落表的操作串行化執(zhí)行。

盡管從業(yè)務(wù)上來說很好理解,但使用Redis作為分布式鎖對(duì)我來說是個(gè)新知識(shí),阿粉打算結(jié)合項(xiàng)目中的代碼,深挖一下這個(gè)知識(shí)點(diǎn)。

正文

1. 為什么要使用分布式鎖

在實(shí)際項(xiàng)目中見過分布式鎖后,就不難理解為什么要使用分布式鎖了:總結(jié)來說就是分布式系統(tǒng)要訪問共享資源,為了避免并發(fā)訪問資源帶來錯(cuò)誤,我們?yōu)楣蚕碣Y源添加一把鎖,讓各個(gè)訪問互斥,保證并發(fā)訪問的安全性,這就是使用分布式鎖的原因。

2. Redis中分布式鎖的實(shí)現(xiàn)

redis中使用分布式鎖很簡單,只要使用setnx指令對(duì)某個(gè)key上鎖就行:

  1. setnx lock test //上鎖 
  2. del lock test   //解鎖 

當(dāng)某個(gè)key沒有被占用的時(shí)候,setnx指令會(huì)返回1,否則返回0,這就是Redis中分布式鎖的使用原理。

當(dāng)然我們還可以在上鎖之后使用expire指令給鎖設(shè)置過期時(shí)間。

看到這里你可能會(huì)有疑問,如果我們的程序流程不使用指令解鎖,靠redis設(shè)置時(shí)間過期來解鎖,貌似會(huì)出問題。假如我們的服務(wù)進(jìn)程在執(zhí)行setnx之后和執(zhí)行expire指令之前掛掉了,那這個(gè)鎖豈不是永遠(yuǎn)都不能被釋放?

 

沒錯(cuò),這確實(shí)是個(gè)問題,當(dāng)時(shí)人們在Redis的開源社區(qū)提出了一堆解決方案專門來解決這個(gè)問題,可實(shí)現(xiàn)方式都極為復(fù)雜。后來Redis的作者在Redis 2.8版本中加入了set指令的擴(kuò)展參數(shù),使得setnx指令和expire指令能夠同時(shí)執(zhí)行,具體使用像下面這個(gè)樣子:

 

  1. set lock test ex 5 nx 
  2. ex:設(shè)置鍵的過期時(shí)間 
  3. nx:只在鍵不存在時(shí),才對(duì)鍵進(jìn)行設(shè)置操作 

從此以后,Redis成為了分布式鎖的寵兒。

3. 分布式鎖在Redis集群中遇到的麻煩

在學(xué)習(xí)了Redis中分布式鎖的使用后,很快我們便發(fā)現(xiàn)了新的問題。在企業(yè)中,Redis基本上都是集群部署的,集群部署避免不了要面對(duì)某個(gè)節(jié)點(diǎn)宕機(jī)的問題。

我們考慮這么一種情況:假設(shè)我們在redis的主節(jié)點(diǎn)上添加了一把分布式鎖,不幸的是主節(jié)點(diǎn)掛掉了,而且主節(jié)點(diǎn)上的鎖還沒有同步到從節(jié)點(diǎn)上,如果此時(shí)有客戶端來請求獲得同一把鎖,那么它將順利地獲得鎖,之前那把鎖會(huì)被無情地忽視掉,這就是分布式鎖在Redis集群中遇到的麻煩。

 

Redis的作者為了解決這個(gè)問題提出了一個(gè)叫Redlock的算法,它的原理是這樣的:當(dāng)上鎖的時(shí)候,把set指令發(fā)送給過半的節(jié)點(diǎn),只要過半的鎖set成功,就認(rèn)為這次加鎖成功;當(dāng)解鎖的時(shí)候,會(huì)向所有的節(jié)點(diǎn)發(fā)送del指令。

從這個(gè)算法的原理可以看出,由于Redlock需要同時(shí)對(duì)多個(gè)節(jié)點(diǎn)進(jìn)行讀寫,因此使用Redlock加分布式鎖的性能要比單機(jī)Redis低很多。因?yàn)橹鲝膹?fù)制出紕漏的概率極低,所以如果對(duì)分布式加鎖過程有一定的容錯(cuò)率的話,可以考慮直接使用set指令;如果追求高可用性,可以考慮使用Redlock算法。

當(dāng)然,高可用性的分布式鎖不只有Redis的Redlock,我們還可以用zookeeper或者支持事務(wù)的數(shù)據(jù)庫做分布式鎖。

❝簡述zookeeper的分布式鎖原理:假設(shè)zk用某個(gè)節(jié)點(diǎn)作為分布式鎖,當(dāng)不同的客戶端到zk競爭這把鎖的時(shí)候,zk會(huì)按順序給不同的客戶端創(chuàng)建一個(gè)子節(jié)點(diǎn),掛在作為分布式鎖的節(jié)點(diǎn)下面。假設(shè)第一個(gè)來到的客戶端為A,第二個(gè)來到的是B,分布式節(jié)點(diǎn)下掛的第一個(gè)節(jié)點(diǎn)就是A,B緊跟著A,且B會(huì)監(jiān)聽著A的生命狀態(tài),當(dāng)A釋放鎖后A會(huì)被刪除,這時(shí)B監(jiān)聽到A被刪除,B接能上位獲得分布式鎖了。❞

在公司的項(xiàng)目中,雖然Redis是以集群的方式部署的,但還是使用最基本的set指令獲取分布式鎖,因?yàn)檫@種方式的性能遠(yuǎn)遠(yuǎn)高于Redlock算法,也高于zk,數(shù)據(jù)庫等分布式鎖實(shí)現(xiàn)方式。

雖然在高性能與低概率的錯(cuò)誤中選擇了高性能,但項(xiàng)目中還是做了其他工作對(duì)錯(cuò)誤情況進(jìn)行兜底的,比如在公司的項(xiàng)目中對(duì)主從復(fù)制時(shí)的錯(cuò)誤情況會(huì)拋出異常,然后根據(jù)異常會(huì)進(jìn)行一些重試的操作。

總結(jié)

這次對(duì)Redis分布式鎖的探索算是加深了自己對(duì)Redis的理解,但我知道Redis的用處還遠(yuǎn)遠(yuǎn)不止分布式鎖和緩存,留著后面繼續(xù)探索吧。

 

責(zé)任編輯:華軒 來源: Java極客技術(shù)
相關(guān)推薦

2016-07-22 17:55:07

云計(jì)算

2022-09-19 18:32:22

函數(shù)編程語言

2024-03-07 07:58:26

Web開發(fā)響應(yīng)媒體查詢工具

2022-07-17 06:53:24

微服務(wù)架構(gòu)

2022-05-05 12:02:45

SCSS函數(shù)開發(fā)

2018-09-02 15:43:56

Python代碼編程語言

2020-12-14 07:51:16

JS 技巧虛值

2010-03-12 09:15:28

Firefox新功能

2019-11-28 15:36:43

Redis數(shù)據(jù)庫高延遲

2025-02-27 07:47:09

2018-09-03 16:05:03

編程語言Python代碼技巧

2019-12-24 09:49:02

微軟英語瀏覽器

2022-04-15 07:51:12

off-heap堆外內(nèi)存JVM

2021-10-22 09:41:26

橋接模式設(shè)計(jì)

2014-12-01 09:41:25

2021-03-18 14:02:56

iOS蘋果細(xì)節(jié)

2022-06-18 23:03:05

Seata分布式事務(wù)

2024-06-28 09:07:19

2018-07-10 11:33:58

計(jì)算器iPhone刪除

2023-01-02 10:08:42

StampedLocAQS框架
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)