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

鎖的基本概念到Redis分布式鎖實(shí)現(xiàn)

云計(jì)算 分布式 Redis
近來(lái),分布式的問(wèn)題被廣泛提及,比如分布式事務(wù)、分布式框架、ZooKeeper、SpringCloud等等。

 近來(lái),分布式的問(wèn)題被廣泛提及,比如分布式事務(wù)、分布式框架、ZooKeeper、SpringCloud等等。本文先回顧鎖的概念,再介紹分布式鎖,以及如何用Redis來(lái)實(shí)現(xiàn)分布式鎖。

一、鎖的基本了解

首先,回顧一下我們工作學(xué)習(xí)中的鎖的概念。

為什么要先講鎖再講分布式鎖呢?

我們都清楚,鎖的作用是要解決多線(xiàn)程對(duì)共享資源的訪(fǎng)問(wèn)而產(chǎn)生的線(xiàn)程安全問(wèn)題,而在平時(shí)生活中用到鎖的情況其實(shí)并不多,可能有些朋友對(duì)鎖的概念和一些基本的使用不是很清楚,所以我們先看鎖,再深入介紹分布式鎖。

[[286783]]

通過(guò)一個(gè)賣(mài)票的小案例來(lái)看,比如大家去搶dota2 ti9門(mén)票,如果不加鎖的話(huà)會(huì)出現(xiàn)什么問(wèn)題?此時(shí)代碼如下:

  1. package Thread; 
  2. import java.util.concurrent.TimeUnit; 
  3.  
  4. public class Ticket { 
  5.  
  6. /** 
  7. * 初始庫(kù)存量 
  8. * */ 
  9. Integer ticketNum = 8
  10.  
  11. public void reduce(int num){ 
  12. //判斷庫(kù)存是否夠用 
  13. if((ticketNum - num) >= 0){ 
  14. try { 
  15. TimeUnit.MILLISECONDS.sleep(200); 
  16. }catch (InterruptedException e){ 
  17. e.printStackTrace(); 
  18. ticketNum -= num; 
  19. System.out.println(Thread.currentThread().getName() + "成功賣(mài)出" 
  20. + num + "張,剩余" + ticketNum + "張票"); 
  21. }else { 
  22. System.err.println(Thread.currentThread().getName() + "沒(méi)有賣(mài)出" 
  23. + num + "張,剩余" + ticketNum + "張票"); 
  24.  
  25. public static void main(String[] args) throws InterruptedException{ 
  26. Ticket ticket = new Ticket(); 
  27. //開(kāi)啟10個(gè)線(xiàn)程進(jìn)行搶票,按理說(shuō)應(yīng)該有兩個(gè)人搶不到票 
  28. for(int i=0;i<10;i++){ 
  29. new Thread(() -> ticket.reduce(1),"用戶(hù)" + (i + 1)).start(); 
  30. Thread.sleep(1000L); 
  31.  

代碼分析:這里有8張ti9門(mén)票,設(shè)置了10個(gè)線(xiàn)程(也就是模擬10個(gè)人)去并發(fā)搶票,如果搶成功了顯示成功,搶失敗的話(huà)顯示失敗。按理說(shuō)應(yīng)該有8個(gè)人搶成功了,2個(gè)人搶失敗,下面來(lái)看運(yùn)行結(jié)果:

Redis专题(3):锁的基本概念到Redis分布式锁实现

我們發(fā)現(xiàn)運(yùn)行結(jié)果和預(yù)期的情況不一致,居然10個(gè)人都買(mǎi)到了票,也就是說(shuō)出現(xiàn)了線(xiàn)程安全的問(wèn)題,那么是什么原因?qū)е碌哪兀?/p>

原因就是多個(gè)線(xiàn)程之間產(chǎn)生了時(shí)間差。

如圖所示,只剩一張票了,但是兩個(gè)線(xiàn)程都讀到的票余量是1,也就是說(shuō)線(xiàn)程B還沒(méi)有等到線(xiàn)程A改庫(kù)存就已經(jīng)搶票成功了。

Redis专题(3):锁的基本概念到Redis分布式锁实现

  1. 怎么解決呢?想必大家都知道,加個(gè)synchronized關(guān)鍵字就可以了,在一個(gè)線(xiàn)程進(jìn)行reduce方法的時(shí)候,其他線(xiàn)程則阻塞在等待隊(duì)列中,這樣就不會(huì)發(fā)生多個(gè)線(xiàn)程對(duì)共享變量的競(jìng)爭(zhēng)問(wèn)題。  
  2. 舉個(gè)例子  
  3. 比如我們?nèi)ソ∩矸拷∩恚绻枚嗳送瑫r(shí)用一臺(tái)機(jī)器,同時(shí)在一臺(tái)跑步機(jī)上跑步,就會(huì)發(fā)生很大的問(wèn)題,大家會(huì)打得不可開(kāi)交。如果我們加一把鎖在健身房門(mén)口,只有拿到鎖的鑰匙的人才可以進(jìn)去鍛煉,其他人在門(mén)外等候,這樣就可以避免大家對(duì)健身器材的競(jìng)爭(zhēng)。代碼如下:  
  4. public  synchronized void reduce(int num){  
  5.         //判斷庫(kù)存是否夠用  
  6.         if((ticketNum - num) >= 0){  
  7.             try {  
  8.                 TimeUnit.MILLISECONDS.sleep(200);  
  9.             }catch (InterruptedException e){  
  10.                 e.printStackTrace();  
  11.             }  
  12.             ticketNum -= num;  
  13.             System.out.println(Thread.currentThread().getName() + "成功賣(mài)出"  
  14.             + num + "張,剩余" + ticketNum + "張票");  
  15.         }else {  
  16.             System.err.println(Thread.currentThread().getName() + "沒(méi)有賣(mài)出"  
  17.                     + num + "張,剩余" + ticketNum + "張票");  
  18.         }  
  19.     }  

運(yùn)行結(jié)果:

Redis专题(3):锁的基本概念到Redis分布式锁实现

果不其然,結(jié)果有兩個(gè)人沒(méi)有成功搶到票,看來(lái)我們的目的達(dá)成了。

二、鎖的性能優(yōu)化

2.1 縮短鎖的持有時(shí)間

事實(shí)上,按照我們對(duì)日常生活的理解,不可能整個(gè)健身房只有一個(gè)人在運(yùn)動(dòng)。所以我們只需要對(duì)某一臺(tái)機(jī)器加鎖就可以了,比如一個(gè)人在跑步,另一個(gè)人可以去做其他的運(yùn)動(dòng)。

對(duì)于票務(wù)系統(tǒng)來(lái)說(shuō),我們只需要對(duì)庫(kù)存的修改操作的代碼加鎖就可以了,別的代碼還是可以并行進(jìn)行,這樣會(huì)大大減少鎖的持有時(shí)間,代碼修改如下:

  1. public void reduceByLock(int num){ 
  2. boolean flag = false
  3. synchronized (ticketNum){ 
  4. if((ticketNum - num) >= 0){ 
  5. ticketNum -= num; 
  6. flag = true
  7. if(flag){ 
  8. System.out.println(Thread.currentThread().getName() + "成功賣(mài)出" 
  9. + num + "張,剩余" + ticketNum + "張票"); 
  10. else { 
  11. System.err.println(Thread.currentThread().getName() + "沒(méi)有賣(mài)出" 
  12. + num + "張,剩余" + ticketNum + "張票"); 
  13. if(ticketNum == 0){ 
  14. System.out.println("耗時(shí)" + (System.currentTimeMillis() - startTime) + "毫秒"); 
  15.  
  16. 這樣做的目的是充分利用cpu的資源,提高代碼的執(zhí)行效率。 
  17. 這里我們對(duì)兩種方式的時(shí)間做個(gè)打印: 
  18. public synchronized void reduce(int num){ 
  19. //判斷庫(kù)存是否夠用 
  20. if((ticketNum - num) >= 0){ 
  21. try { 
  22. TimeUnit.MILLISECONDS.sleep(200); 
  23. }catch (InterruptedException e){ 
  24. e.printStackTrace(); 
  25. ticketNum -= num; 
  26. if(ticketNum == 0){ 
  27. System.out.println("耗時(shí)" + (System.currentTimeMillis() - startTime) + "毫秒"); 
  28. System.out.println(Thread.currentThread().getName() + "成功賣(mài)出" 
  29. + num + "張,剩余" + ticketNum + "張票"); 
  30. }else { 
  31. System.err.println(Thread.currentThread().getName() + "沒(méi)有賣(mài)出" 
  32. + num + "張,剩余" + ticketNum + "張票"); 

Redis专题(3):锁的基本概念到Redis分布式锁实现

Redis专题(3):锁的基本概念到Redis分布式锁实现

果然,只對(duì)部分代碼加鎖會(huì)大大提供代碼的執(zhí)行效率。

所以,在解決了線(xiàn)程安全的問(wèn)題后,我們還要考慮到加鎖之后的代碼執(zhí)行效率問(wèn)題。

2.2 減少鎖的粒度

舉個(gè)例子,有兩場(chǎng)電影,分別是最近剛上映的魔童哪吒和蜘蛛俠,我們模擬一個(gè)支付購(gòu)買(mǎi)的過(guò)程,讓方法等待,加了一個(gè)CountDownLatch的await方法,運(yùn)行結(jié)果如下:

  1. package Thread; 
  2. import java.util.concurrent.CountDownLatch; 
  3.  
  4. public class Movie { 
  5. private final CountDownLatch latch = new CountDownLatch(1); 
  6. //魔童哪吒 
  7. private Integer babyTickets = 20
  8.  
  9. //蜘蛛俠 
  10. private Integer spiderTickets = 100
  11.  
  12. public synchronized void showBabyTickets() throws InterruptedException{ 
  13. System.out.println("魔童哪吒的剩余票數(shù)為:" + babyTickets); 
  14. //購(gòu)買(mǎi) 
  15. latch.await(); 
  16.  
  17. public synchronized void showSpiderTickets() throws InterruptedException{ 
  18. System.out.println("蜘蛛俠的剩余票數(shù)為:" + spiderTickets); 
  19. //購(gòu)買(mǎi) 
  20.  
  21. public static void main(String[] args) { 
  22. Movie movie = new Movie(); 
  23. new Thread(() -> { 
  24. try { 
  25. movie.showBabyTickets(); 
  26. }catch (InterruptedException e){ 
  27. e.printStackTrace(); 
  28. },"用戶(hù)A").start(); 
  29.  
  30. new Thread(() -> { 
  31. try { 
  32. movie.showSpiderTickets(); 
  33. }catch (InterruptedException e){ 
  34. e.printStackTrace(); 
  35. },"用戶(hù)B").start(); 
  36.  

執(zhí)行結(jié)果:

魔童哪吒的剩余票數(shù)為:20

我們發(fā)現(xiàn)買(mǎi)哪吒票的時(shí)候阻塞會(huì)影響蜘蛛俠票的購(gòu)買(mǎi),而實(shí)際上,這兩場(chǎng)電影之間是相互獨(dú)立的,所以我們需要減少鎖的粒度,將movie整個(gè)對(duì)象的鎖變?yōu)閮蓚€(gè)全局變量的鎖,修改代碼如下:

  1. public void showBabyTickets() throws InterruptedException{ 
  2. synchronized (babyTickets) { 
  3. System.out.println("魔童哪吒的剩余票數(shù)為:" + babyTickets); 
  4. //購(gòu)買(mǎi) 
  5. latch.await(); 
  6. public void showSpiderTickets() throws InterruptedException{ 
  7. synchronized (spiderTickets) { 
  8. System.out.println("蜘蛛俠的剩余票數(shù)為:" + spiderTickets); 
  9. //購(gòu)買(mǎi) 

 

執(zhí)行結(jié)果:

魔童哪吒的剩余票數(shù)為:20

蜘蛛俠的剩余票數(shù)為:100

現(xiàn)在兩場(chǎng)電影的購(gòu)票不會(huì)互相影響了,這就是第二個(gè)優(yōu)化鎖的方式:減少鎖的粒度。順便提一句,Java并發(fā)包里的ConcurrentHashMap就是把一把大鎖變成了16把小鎖,通過(guò)分段鎖的方式達(dá)到高效的并發(fā)安全。

2.3 鎖分離

鎖分離就是常說(shuō)的讀寫(xiě)分離,我們把鎖分成讀鎖和寫(xiě)鎖,讀的鎖不需要阻塞,而寫(xiě)的鎖要考慮并發(fā)問(wèn)題。

三、鎖的種類(lèi)

  • 公平鎖:ReentrantLock
  • 非公平鎖:Synchronized、ReentrantLock、cas
  • 悲觀鎖:Synchronized
  • 樂(lè)觀鎖:cas
  • 獨(dú)享鎖:Synchronized、ReentrantLock
  • 共享鎖:Semaphore

這里就不一一講述每一種鎖的概念了,大家可以自己學(xué)習(xí),鎖還可以按照偏向鎖、輕量級(jí)鎖、重量級(jí)鎖來(lái)分類(lèi)。

四、Redis分布式鎖

了解了鎖的基本概念和鎖的優(yōu)化后,重點(diǎn)介紹分布式鎖的概念。

Redis专题(3):锁的基本概念到Redis分布式锁实现

上圖所示是我們搭建的分布式環(huán)境,有三個(gè)購(gòu)票項(xiàng)目,對(duì)應(yīng)一個(gè)庫(kù)存,每一個(gè)系統(tǒng)會(huì)有多個(gè)線(xiàn)程,和上文一樣,對(duì)庫(kù)存的修改操作加上鎖,能不能保證這6個(gè)線(xiàn)程的線(xiàn)程安全呢?

當(dāng)然是不能的,因?yàn)槊恳粋€(gè)購(gòu)票系統(tǒng)都有各自的JVM進(jìn)程,互相獨(dú)立,所以加synchronized只能保證一個(gè)系統(tǒng)的線(xiàn)程安全,并不能保證分布式的線(xiàn)程安全。

所以需要對(duì)于三個(gè)系統(tǒng)都是公共的一個(gè)中間件來(lái)解決這個(gè)問(wèn)題。

這里我們選擇Redis來(lái)作為分布式鎖,多個(gè)系統(tǒng)在Redis中set同一個(gè)key,只有key不存在的時(shí)候,才能設(shè)置成功,并且該key會(huì)對(duì)應(yīng)其中一個(gè)系統(tǒng)的唯一標(biāo)識(shí),當(dāng)該系統(tǒng)訪(fǎng)問(wèn)資源結(jié)束后,將key刪除,則達(dá)到了釋放鎖的目的。

4.1 分布式鎖需要注意哪些點(diǎn)

1)互斥性

在任意時(shí)刻只有一個(gè)客戶(hù)端可以獲取鎖。

這個(gè)很容易理解,所有的系統(tǒng)中只能有一個(gè)系統(tǒng)持有鎖。

2)防死鎖

假如一個(gè)客戶(hù)端在持有鎖的時(shí)候崩潰了,沒(méi)有釋放鎖,那么別的客戶(hù)端無(wú)法獲得鎖,則會(huì)造成死鎖,所以要保證客戶(hù)端一定會(huì)釋放鎖。

Redis中我們可以設(shè)置鎖的過(guò)期時(shí)間來(lái)保證不會(huì)發(fā)生死鎖。

3)持鎖人解鎖

解鈴還須系鈴人,加鎖和解鎖必須是同一個(gè)客戶(hù)端,客戶(hù)端A的線(xiàn)程加的鎖必須是客戶(hù)端A的線(xiàn)程來(lái)解鎖,客戶(hù)端不能解開(kāi)別的客戶(hù)端的鎖。

4)可重入

當(dāng)一個(gè)客戶(hù)端獲取對(duì)象鎖之后,這個(gè)客戶(hù)端可以再次獲取這個(gè)對(duì)象上的鎖。

4.2 Redis分布式鎖流程

Redis专题(3):锁的基本概念到Redis分布式锁实现

Redis分布式鎖的具體流程:

1)首先利用Redis緩存的性質(zhì)在Redis中設(shè)置一個(gè)key-value形式的鍵值對(duì),key就是鎖的名稱(chēng),然后客戶(hù)端的多個(gè)線(xiàn)程去競(jìng)爭(zhēng)鎖,競(jìng)爭(zhēng)成功的話(huà)將value設(shè)為客戶(hù)端的唯一標(biāo)識(shí)。

2)競(jìng)爭(zhēng)到鎖的客戶(hù)端要做兩件事:

  • 設(shè)置鎖的有效時(shí)間 目的是防死鎖 (非常關(guān)鍵)

需要根據(jù)業(yè)務(wù)需要,不斷的壓力測(cè)試來(lái)決定有效期的長(zhǎng)短。

  • 分配客戶(hù)端的唯一標(biāo)識(shí),目的是保證持鎖人解鎖(非常重要)

所以這里的value就設(shè)置成唯一標(biāo)識(shí)(比如uuid)。

3)訪(fǎng)問(wèn)共享資源

4)釋放鎖,釋放鎖有兩種方式,第一種是有效期結(jié)束后自動(dòng)釋放鎖,第二種是先根據(jù)唯一標(biāo)識(shí)判斷自己是否有釋放鎖的權(quán)限,如果標(biāo)識(shí)正確則釋放鎖。

4.3 加鎖和解鎖

4.3.1 加鎖

1)setnx命令加鎖

set if not exists 我們會(huì)用到Redis的命令setnx,setnx的含義就是只有鎖不存在的情況下才會(huì)設(shè)置成功。

2)設(shè)置鎖的有效時(shí)間,防止死鎖 expire

加鎖需要兩步操作,思考一下會(huì)有什么問(wèn)題嗎?

假如我們加鎖完之后客戶(hù)端突然掛了呢?那么這個(gè)鎖就會(huì)成為一個(gè)沒(méi)有有效期的鎖,接著就可能發(fā)生死鎖。雖然這種情況發(fā)生的概率很小,但是一旦出現(xiàn)問(wèn)題會(huì)很?chē)?yán)重,所以我們也要把這兩步合為一步。

幸運(yùn)的是,Redis3.0已經(jīng)把這兩個(gè)指令合在一起成為一個(gè)新的指令。

來(lái)看jedis的官方文檔中的源碼:

  1. public String set(String key, String value, String nxxx, String expx, long time) { 
  2. this.checkIsInMultiOrPipeline(); 
  3. this.client.set(key, value, nxxx, expx, time); 
  4. return this.client.getStatusCodeReply(); 

 

這就是我們想要的!

4.3.2 解鎖

  1. 檢查是否自己持有鎖(判斷唯一標(biāo)識(shí));
  2. 刪除鎖。

解鎖也是兩步,同樣也要保證解鎖的原子性,把兩步合為一步。

這就無(wú)法借助于Redis了,只能依靠Lua腳本來(lái)實(shí)現(xiàn)。

  1. if Redis.call("get",key==argv[1])then 
  2. return Redis.call("del",key) 
  3. else return 0 end 

 

這就是一段判斷是否自己持有鎖并釋放鎖的Lua腳本。

為什么Lua腳本是原子性呢?因?yàn)長(zhǎng)ua腳本是jedis用eval()函數(shù)執(zhí)行的,如果執(zhí)行則會(huì)全部執(zhí)行完成。

五、Redis分布式鎖代碼實(shí)現(xiàn)

  1. public class RedisDistributedLock implements Lock { 
  2. //上下文,保存當(dāng)前鎖的持有人id 
  3. private ThreadLocal<String> lockContext = new ThreadLocal<String>(); 
  4.  
  5. //默認(rèn)鎖的超時(shí)時(shí)間 
  6. private long time = 100
  7.  
  8. //可重入性 
  9. private Thread ownerThread; 
  10.  
  11. public RedisDistributedLock() { 
  12.  
  13. public void lock() { 
  14. while (!tryLock()){ 
  15. try { 
  16. Thread.sleep(100); 
  17. }catch (InterruptedException e){ 
  18. e.printStackTrace(); 
  19.  
  20. public boolean tryLock() { 
  21. return tryLock(time,TimeUnit.MILLISECONDS); 
  22.  
  23. public boolean tryLock(long time, TimeUnit unit){ 
  24. String id = UUID.randomUUID().toString(); //每一個(gè)鎖的持有人都分配一個(gè)唯一的id 
  25. Thread t = Thread.currentThread(); 
  26. Jedis jedis = new Jedis("127.0.0.1",6379); 
  27. //只有鎖不存在的時(shí)候加鎖并設(shè)置鎖的有效時(shí)間 
  28. if("OK".equals(jedis.set("lock",id, "NX""PX", unit.toMillis(time)))){ 
  29. //持有鎖的人的id 
  30. lockContext.set(id); ① 
  31. //記錄當(dāng)前的線(xiàn)程 
  32. setOwnerThread(t); ② 
  33. return true
  34. }else if(ownerThread == t){ 
  35. //因?yàn)殒i是可重入的,所以需要判斷當(dāng)前線(xiàn)程已經(jīng)持有鎖的情況 
  36. return true
  37. }else { 
  38. return false
  39.  
  40. private void setOwnerThread(Thread t){ 
  41. this.ownerThread = t; 
  42.  
  43. public void unlock() { 
  44. String script = null
  45. try
  46. Jedis jedis = new Jedis("127.0.0.1",6379); 
  47. script = inputStream2String(getClass().getResourceAsStream("/Redis.Lua")); 
  48. if(lockContext.get()==null){ 
  49. //沒(méi)有人持有鎖 
  50. return
  51. //刪除鎖 ③ 
  52. jedis.eval(script, Arrays.asList("lock"), Arrays.asList(lockContext.get())); 
  53. lockContext.remove(); 
  54. }catch (Exception e){ 
  55. e.printStackTrace(); 
  56.  
  57. /** 
  58. * 將InputStream轉(zhuǎn)化成String 
  59. * @param is 
  60. * @return 
  61. * @throws IOException 
  62. */ 
  63. public String inputStream2String(InputStream is) throws IOException { 
  64. ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
  65. int i = -1
  66. while ((i = is.read()) != -1) { 
  67. baos.write(i); 
  68. return baos.toString(); 
  69.  
  70. public void lockInterruptibly() throws InterruptedException { 
  71.  
  72.  
  73. public Condition newCondition() { 
  74. return null
  • 用一個(gè)上下文全局變量來(lái)記錄持有鎖的人的uuid,解鎖的時(shí)候需要將該uuid作為參數(shù)傳入Lua腳本中,來(lái)判斷是否可以解鎖。
  • 要記錄當(dāng)前線(xiàn)程,來(lái)實(shí)現(xiàn)分布式鎖的重入性,如果是當(dāng)前線(xiàn)程持有鎖的話(huà),也屬于加鎖成功。
  • 用eval函數(shù)來(lái)執(zhí)行Lua腳本,保證解鎖時(shí)的原子性。

六、分布式鎖的對(duì)比

6.1 基于數(shù)據(jù)庫(kù)的分布式鎖

1)實(shí)現(xiàn)方式

獲取鎖的時(shí)候插入一條數(shù)據(jù),解鎖時(shí)刪除數(shù)據(jù)。

2)缺點(diǎn)

  • 數(shù)據(jù)庫(kù)如果掛掉會(huì)導(dǎo)致業(yè)務(wù)系統(tǒng)不可用。
  • 無(wú)法設(shè)置過(guò)期時(shí)間,會(huì)造成死鎖。

6.2 基于zookeeper的分布式鎖

1)實(shí)現(xiàn)方式

加鎖時(shí)在指定節(jié)點(diǎn)的目錄下創(chuàng)建一個(gè)新節(jié)點(diǎn),釋放鎖的時(shí)候刪除這個(gè)臨時(shí)節(jié)點(diǎn)。因?yàn)橛行奶鴻z測(cè)的存在,所以不會(huì)發(fā)生死鎖,更加安全。

2)缺點(diǎn)

性能一般,沒(méi)有Redis高效。

所以:

  • 從性能角度: Redis > zookeeper > 數(shù)據(jù)庫(kù) 
  • 從可靠性(安全)性角度: zookeeper > Redis > 數(shù)據(jù)庫(kù)

七、總結(jié)

本文從鎖的基本概念出發(fā),提出多線(xiàn)程訪(fǎng)問(wèn)共享資源會(huì)出現(xiàn)的線(xiàn)程安全問(wèn)題,然后通過(guò)加鎖的方式去解決線(xiàn)程安全的問(wèn)題,這個(gè)方法會(huì)性能會(huì)下降,需要通過(guò):縮短鎖的持有時(shí)間、減小鎖的粒度、鎖分離三種方式去優(yōu)化鎖。

之后介紹了分布式鎖的4個(gè)特點(diǎn):

  • 互斥性 
  • 防死鎖 
  • 加鎖人解鎖 
  • 可重入性

然后用Redis實(shí)現(xiàn)了分布式鎖,加鎖的時(shí)候用到了Redis的命令去加鎖,解鎖的時(shí)候則借助了Lua腳本來(lái)保證原子性。

最后對(duì)比了三種分布式鎖的優(yōu)缺點(diǎn)和使用場(chǎng)景。

希望大家對(duì)分布式鎖有新的理解,也希望大家在考慮解決問(wèn)題的同時(shí)要多想想性能的問(wèn)題。

【本文是51CTO專(zhuān)欄機(jī)構(gòu)宜信技術(shù)學(xué)院的原創(chuàng)文章,微信公眾號(hào)“宜信技術(shù)學(xué)院( id: CE_TECH)”】

戳這里,看該作者更多好文

 

 

責(zé)任編輯:張燕妮 來(lái)源: 宜信技術(shù)學(xué)院
相關(guān)推薦

2022-01-06 10:58:07

Redis數(shù)據(jù)分布式鎖

2023-08-21 19:10:34

Redis分布式

2019-06-19 15:40:06

分布式鎖RedisJava

2019-02-26 09:51:52

分布式鎖RedisZookeeper

2024-10-07 10:07:31

2024-04-01 05:10:00

Redis數(shù)據(jù)庫(kù)分布式鎖

2023-03-01 08:07:51

2024-11-28 15:11:28

2020-07-16 20:55:19

ElasticSear集群分布式

2020-07-30 09:35:09

Redis分布式鎖數(shù)據(jù)庫(kù)

2020-07-15 16:50:57

Spring BootRedisJava

2023-10-11 09:37:54

Redis分布式系統(tǒng)

2022-06-16 08:01:24

redis分布式鎖

2021-10-25 10:21:59

ZK分布式鎖ZooKeeper

2021-02-28 07:49:28

Zookeeper分布式

2018-04-03 16:24:34

分布式方式

2017-01-16 14:13:37

分布式數(shù)據(jù)庫(kù)

2017-04-13 10:51:09

Consul分布式

2022-04-08 08:27:08

分布式鎖系統(tǒng)

2022-03-04 09:54:04

Redis分布式鎖腳本
點(diǎn)贊
收藏

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

主站蜘蛛池模板: 成人国产免费观看 | 久久骚 | 成人亚洲一区 | 亚洲精品乱码 | 亚洲精品久久久 | 亚洲精品视频一区二区三区 | 日韩中文字幕在线观看视频 | 日韩成人专区 | 国产 日韩 欧美 中文 在线播放 | 日韩视频在线观看一区二区 | 99久久久国产精品 | 日韩欧美一区二区三区 | 午夜影院视频在线观看 | 中文字幕成人网 | 99日韩| 中文字幕精品视频在线观看 | www日韩| 免费在线观看av网址 | 综合二区 | 一区二区三区中文字幕 | 黄网在线观看 | www.日本在线 | 91精品国产综合久久久久久丝袜 | 色久伊人 | 女同久久另类99精品国产 | 国产乱码久久久 | 久草在线视频中文 | 一区中文字幕 | 日韩电影免费在线观看中文字幕 | 免费av直接看 | 草草草影院 | 黄色视频a级毛片 | 午夜综合| 在线观看中文视频 | 狠狠色综合网站久久久久久久 | 欧美区在线| 欧美成年黄网站色视频 | 成人一区二区三区 | 精品欧美一区二区三区免费观看 | 一区二区三区四区在线视频 | 中文字幕在线一区二区三区 |