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

Redis 做分布式鎖你會幾種姿勢?給大家介紹兩種

存儲 分布式 Redis
Redis 簡簡單單的幾種數(shù)據(jù)類型,一個 key/value 數(shù)據(jù)庫,現(xiàn)在又是分布式鎖、又是限流工具、又是消息隊列......,感覺都要被玩壞了。不過話說回來,Redis 在這么多場合被開發(fā)者們喜歡,還是得益于它極高的性能與使用的簡潔性。

[[318373]]

本文大綱:

1.什么是分布式鎖

2.解決方案

  • 2.1 整體思路
  • 2.2 解決方案一
  • 2.3 解決方案二

3.小結(jié)

Redis 簡簡單單的幾種數(shù)據(jù)類型,一個 key/value 數(shù)據(jù)庫,現(xiàn)在又是分布式鎖、又是限流工具、又是消息隊列......,感覺都要被玩壞了。不過話說回來,Redis 在這么多場合被開發(fā)者們喜歡,還是得益于它極高的性能與使用的簡潔性。

在面試的時候,說到 Redis ,很多人第一反應就是緩存,其實除了緩存,Redis 還有非常多豐富的使用場景,這些使用場景,松哥在未來都會和大家一一分享。

今天就先來看一個簡單的,用 Redis 做分布式鎖。

1.什么是分布式鎖首先我們來看一個問題場景:

例如一個簡單的用戶操作,一個線程去修改用戶的狀態(tài),首先從數(shù)據(jù)庫中讀出用戶的狀態(tài),然后在內(nèi)存中進行修改,修改完成后,再存回去。在單線程中,這個操作沒有問題,但是在多線程中,由于讀取、修改、存 這是三個操作,不是原子操作,所以在多線程中,這樣會出問題。

解決這個問題,我們就需要鎖,對于鎖,大家應該不會陌生,在 Java 中的 synchronized 以及 ReentrantLock 可重入鎖都是我們比較常見的,但是這種鎖都是本地鎖,現(xiàn)在微服務、分布式系統(tǒng)思想大行其道,在這樣的系統(tǒng)中,本地鎖顯然是不夠用的,于是大家紛紛想辦法,如何在分布式環(huán)境下解決鎖的問題。想出來的辦法很多,我們可以通過 MySQL、可以通過 ZK、也可以通過 Redis ,都可以用來解決分布式鎖的問題,這里我們主要來看看如何通過 Redis 解決分布式鎖問題。

2.解決方案

2.1 整體思路

「分布式鎖實現(xiàn)的思路很簡單,就是進來一個線城先占位,當別的線城進來操作時,發(fā)現(xiàn)已經(jīng)有人占位了,就會放棄或者稍后再試?!?/p>

在 Redis 中,占位一般使用 setnx 指令,先進來的線程先占位,線程的操作執(zhí)行完成后,再調(diào)用 del 指令釋放位子。同時為了防止死鎖,我們一般還要給鎖加一個過期時間,到期了自動釋放。

基于這樣的思路,我們來看兩種不同的實現(xiàn)方式:

2.2 解決方案一

基于我們前面所說的思路,可以使用 setnx 和 expire 實現(xiàn)分布式鎖,但是 setnx 和設置過期時間 expire 這是兩個操作,這兩個操作一起的話就不具備原子性(除非自己寫 Lua 腳本),為了解決這個問題,從 Redis2.8 開始,setnx 和 expire 可以通過一個命令一起來執(zhí)行了,這個命令就是 set,set 中多了一個參數(shù): 

 從圖中大家可以看到,在 key/value 之后,還有一個 EX 5 表示以秒計的過期時間(PX 表示以毫秒計的過期時間),最后的 NX 就是說如果 k1 不存在,這條命令執(zhí)行成功,否則執(zhí)行失敗,這就相當于 setnx 的效果了。

因此,我們封裝的鎖如下: 

  1. public class LockTest { 
  2.     public static void main(String[] args) { 
  3.         Redis redis = new Redis(); 
  4.         redis.execute(jedis->{ 
  5.             String set = jedis.set("k1""v1", new SetParams().nx().ex(5)); 
  6.             if (set !=null && "OK".equals(set)) { 
  7.                 //沒人占位 
  8.                 jedis.set("name""javaboy"); 
  9.                 String name = jedis.get("name"); 
  10.                 System.out.println(name); 
  11.                 jedis.del("k1");//釋放資源 
  12.             }else
  13.                 //有人占位,停止/暫緩 操作 
  14.             } 
  15.         }); 
  16.     } 

對于上面這段代碼,大家重點看思路,不必深究代碼細節(jié):

  1. 首先構(gòu)造一個 Redis 實例,然后調(diào)用 execute 方法,這個是我自己封裝的方法,目的是為了配置 Jedis 連接池并及時回收使用過的資源。這一塊小伙伴們測試的時候可以直接使用自己創(chuàng)建的 Jedis 實例,效果是一樣的。
  2. 調(diào)用 jedis 中的 set 方法,注意第三個參數(shù),我們設置了 nx 同時 設置了過期時間為 5 秒,這就相當于 setnx 和 expire 兩個命令的結(jié)合體。
  3. 如果成功執(zhí)行了 set 命令,在 if 中就可以去寫自己的業(yè)務了。如果沒能搶到鎖,則可以進入到一個延遲消息隊列中,停一會再去嘗試(用 Redis 實現(xiàn)延遲消息隊列,松哥會在后面的文章中向大家介紹)。

2.3 解決方案二

上面的代碼寫著還是蠻長的,那么有沒有簡單一點的辦法呢?當然是有的!那就是 Redisson。

相對于 Jedis 這種原生態(tài)的應用,Redisson 對 Redis 請求做了較多的封裝,對于鎖,也提供了對應的方法可以直接使用: 

  1. Config config = new Config(); 
  2. //配置 Redis 基本連接信息 
  3. config.useSingleServer().setAddress("redis://127.0.0.1:6379").setPassword("123"); 
  4. //獲取一個 RedissonClient 對象 
  5. RedissonClient redisson = Redisson.create(config); 
  6. //獲取一個鎖對象實例 
  7. RLock lock = redisson.getLock("lock"); 
  8. try { 
  9.     //獲取鎖 
  10.     boolean b = lock.tryLock(500, 1000, TimeUnit.MILLISECONDS); 
  11.     if (b) { 
  12.         //獲取到鎖了,開始寫業(yè)務 
  13.         RBucket<Object> bucket = redisson.getBucket("javaboy"); 
  14.         bucket.set("www.javaboy.org"); 
  15.         Object o = bucket.get(); 
  16.         System.out.println(o); 
  17.     }else
  18.         System.out.println("沒拿到鎖"); 
  19.     } 
  20. } catch (InterruptedException e) { 
  21.     e.printStackTrace(); 
  22. } finally { 
  23.     //釋放鎖 
  24.     lock.unlock(); 

在這段代碼中,核心的就是 lock.tryLock(500, 1000, TimeUnit.MILLISECONDS);,第一個參數(shù)是嘗試加鎖的等待時間為 500 毫秒,第二個參數(shù)表示鎖的超時時間為 1000 毫秒,也就是這個鎖在 1000 毫秒后會自動失效。

小伙伴們發(fā)現(xiàn),這和我們在方案一里邊配置的參數(shù)是一樣的,其實思路是不變的,Redisson 只不過是將我們寫的和鎖相關的方法封裝起來了而已。

3.小結(jié)

當然,這里我只是先簡單介紹下加鎖的思路以及在 Redis 單機中如何加鎖,后面松哥再和大家分享 Redis 集群中如何加鎖。

 

責任編輯:武曉燕 來源: 江南一點雨
相關推薦

2022-05-18 10:38:51

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

2023-03-01 08:07:51

2021-03-07 16:11:26

Redis分布式

2019-06-19 15:40:06

分布式鎖RedisJava

2023-04-03 10:00:00

Redis分布式

2022-07-06 08:01:05

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

2022-02-10 08:57:45

分布式線程鎖

2010-06-03 19:28:02

Hadoop

2022-01-06 10:58:07

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

2023-08-21 19:10:34

Redis分布式

2019-02-26 09:51:52

分布式鎖RedisZookeeper

2014-05-21 11:00:55

Windows Azu分布式部署

2021-04-02 09:50:14

微服務分布式鎖Java

2020-11-16 12:55:41

Redis分布式鎖Zookeeper

2024-10-07 10:07:31

2022-09-19 08:17:09

Redis分布式

2020-10-19 07:30:57

Java Redis 開發(fā)

2023-09-13 09:52:14

分布式鎖Java

2019-07-16 09:22:10

RedisZookeeper分布式鎖

2021-06-16 07:56:21

Redis分布式
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲欧洲成人在线 | 中文字幕爱爱视频 | 在线观看中文字幕亚洲 | 精品久久久久久久久久久久久久久久久 | 国产精品视频一二三区 | 九九九久久国产免费 | 在线播放亚洲 | 黄色成人在线观看 | 婷婷成人在线 | 99精品免费久久久久久久久日本 | 六月色婷 | 亚洲乱码一区二区三区在线观看 | 视频一区在线 | 无码一区二区三区视频 | 日韩免费视频一区二区 | 玖玖在线免费视频 | 久久福利电影 | 欧美美女被c | 成人av电影天堂 | av黄色片在线观看 | 国产精品国产三级国产aⅴ中文 | 亚洲精品电影在线观看 | 天天影视亚洲综合网 | 国产免费一区二区 | 成人亚洲性情网站www在线观看 | 亚洲免费在线观看 | 久久国产精品-国产精品 | 不卡在线视频 | 国产一区二区三区免费观看视频 | 欧美一区免费 | 久久久黄色 | 久久精品视频9 | 亚洲一区二区三区在线免费观看 | 免费看黄色国产 | 欧美日本韩国一区二区三区 | 99久久久久国产精品免费 | 欧美日韩在线一区二区三区 | 黄色在线免费网站 | 国产高清精品在线 | 精品久久99| 二区久久|