偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

夜深人靜了,我們來學學分布式鎖

開發(fā) 前端 分布式
記錄一下今天的文章開始寫的時間00:53,夜深人靜了,我們來學一下分布式鎖,我們要悄悄地學習,然后經驗所有人。

[[354141]]

本文轉載自微信公眾號「故里學Java」,作者故里 。轉載本文請聯(lián)系故里學Java公眾號。  

記錄一下今天的文章開始寫的時間00:53,夜深人靜了,我們來學一下分布式鎖,我們要悄悄地學習,然后經驗所有人。

什么是分布式鎖?分布式鎖又可以解決哪些問題呢?

在我們的系統(tǒng)還沒有使用分布式架構的時候,我們可以用同步鎖或者Lock鎖,來保證多線程并發(fā)的時候,同一時間只有一個線程修改共享變量或者執(zhí)行代碼塊,但是當我們現(xiàn)在大部分系統(tǒng)都是分布式集群部署的,單純的同步鎖和Lock鎖只能保證單個實例上的數(shù)據(jù)一致性,多實例就失去了作用。

這個時候就需要使用分布式鎖來保證共享資源的原子性,比如我們電商系統(tǒng)里面的扣減庫存,當單量小的時候問題不大,如果單量很大,同一時間多個實例都在并發(fā)處理扣減庫存的業(yè)務的時候,就可能存在超賣的問題。

分布式鎖的實現(xiàn)?

常見的分布式鎖有數(shù)據(jù)庫實現(xiàn)分布式鎖、Zookeeper實現(xiàn)分布式鎖、Redis實現(xiàn)分布式鎖、Redisson實現(xiàn)。其中數(shù)據(jù)庫實現(xiàn)分布式鎖比較簡單,也很容易理解,直接基于數(shù)據(jù)庫實現(xiàn)就可以了,在一些分布式的業(yè)務中也經常使用,但是這種方式也是效率最低的,一般是不使用的,我們就著重介紹一下其他三種方式的實現(xiàn)。

Zookeeper實現(xiàn)分布式鎖

使用Zookeeper來實現(xiàn)分布式鎖就比較常見,比如很多項目就使用Zookeeper作為分布式注冊中心,就喜歡用Zookeeper來實現(xiàn)分布式鎖,這主要是借助于Zookeeper的兩大特性:順序臨時節(jié)點、Watch機制。

順序臨時節(jié)點:熟悉Zookeeper的同學都知道,Zookeeper提供了多層級的節(jié)點命名空間,每個節(jié)點都是用斜杠分隔的路徑來表示,類似于我們的文件夾。節(jié)點又分為持久節(jié)點和臨時節(jié)點,節(jié)點還可以標記為有序,當節(jié)點被標記為有序性,這個節(jié)點就具有順序自增的特點,我們就可以借助這個特點來創(chuàng)建我們所需的節(jié)點。

Watch機制:Watch機制是Zookeeper另一個重要的特性,我們可以在指定節(jié)點上注冊一些Watcher,在一些特定的事情觸發(fā)的時候,通知用戶這個事件。

Zookeeper實現(xiàn)分布式鎖的過程

我們先創(chuàng)建一個持久節(jié)點作為父節(jié)點,每當需要訪問創(chuàng)建分布式鎖的時候,就在這個父節(jié)點下創(chuàng)建相應的臨時的順序子節(jié)點,以臨時節(jié)點名稱、父節(jié)點名稱和順序號組成特點的名稱。在建立子節(jié)點后,對父節(jié)點下以這個這個子節(jié)點名稱開頭的子節(jié)點進行排序,判斷剛建立的節(jié)點順序號是不是最小的,如果是最小的則獲取鎖,如果不是最小節(jié)點,則阻塞等待鎖,并且在獲取該節(jié)點的上一順序節(jié)點注冊Watcher,等待節(jié)點對應的操作獲得鎖。

當業(yè)務處理完之后,刪除該節(jié)點,關閉zk,進而觸發(fā)Watcher,釋放該鎖。

上圖就是就是嚴格按照順序訪問的分布式鎖實現(xiàn),更多的時候我們引入一些框架來幫助我們實現(xiàn),比如最常用的Curator框架,代碼如下:

  1. InterProcessMutex lock = new InterProcessMutex(client, lockPath); 
  2. if ( lock.acquire(maxWait, waitUnit) ) { 
  3.     try { 
  4.         // 業(yè)務處理 
  5.     } 
  6.     finally{ 
  7.         lock.release(); 
  8.     } 

Zookeeper來實現(xiàn)分布式鎖天然的優(yōu)勢就是,Zookeeper是集群實現(xiàn)的,我們生產環(huán)境一般也是集群部署的,可以避免單點問題,穩(wěn)定性較好,能保證每次操作都可以釋放鎖。

缺點就是,頻繁的創(chuàng)建刪除節(jié)點,加上注冊watch事件,對于zookeeper集群的壓力比較大,性能這一塊也比不上Redis實現(xiàn)的分布式鎖。

Redis實現(xiàn)分布式鎖

Redis實現(xiàn)的分布式鎖,最為復雜,但是性能確是最佳的,所以在對性能要求更高的系統(tǒng)里,我們都選擇使用Redis來實現(xiàn)分布式鎖。利用Redis實現(xiàn)分布式鎖,一般都是使用SETNX實現(xiàn),舉個簡單的例子:

  1. public static boolean getDistributedLock(Jedis jedis, String lockKey, String requestId, int expireTime) { 
  2.  
  3.     String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime); 
  4.  
  5.     if ("OK".equals(result)) { 
  6.          return true
  7.     } 
  8.     return false

SETNX方法保證設置鎖和鎖過期時間的原子性,但是對于鎖的過期時間設置我們要注意,如果執(zhí)行業(yè)務

時間比較長,我們設置的過期時間又比較短的情況下就會造成,業(yè)務還沒執(zhí)行完,鎖已釋放的問題。所以我們需要根據(jù)實際業(yè)務處理來評估設置鎖的過期時間,來保證業(yè)務可以正常的處理完。

Redisson實現(xiàn)分布式鎖

Redisson是架設在Redis基礎上的一個Java駐內存數(shù)據(jù)網格。Redisson在基于NIO的Netty框架上,充分的利用了Redis鍵值數(shù)據(jù)庫提供的一系列優(yōu)勢,在Java實用工具包中常用接口的基礎上,為使用者提供了一系列具有分布式特性的常用工具類。性能也比我們常用的jedis好一些。

Redisson不管是單節(jié)點模式還是集群模式,都很好的實現(xiàn)了分布式鎖,一般用的多的都是集群模式,在集群模式下,Redisson使用RedLock算法,很好的處理了Master節(jié)點宕機時切換到另外一個Master節(jié)點過程中多個應用獲得鎖。

Redisson集群模式獲取鎖的實現(xiàn)就是,在不同節(jié)點上獲取鎖,每個節(jié)點上獲取鎖都有超時時間,如果獲取鎖超時就認為這個節(jié)點不可用,當成功獲取鎖的個數(shù)超過Redis節(jié)點的半數(shù),且獲取鎖消耗的時間還沒超過鎖過期時間,則認為獲取鎖成功。獲取鎖成功后重新計算鎖釋放時間,由原來的鎖釋放時間減去獲取鎖消耗的時間,如果最終獲取鎖失敗,已經獲取鎖成功的節(jié)點也會釋放鎖。

具體的代碼實現(xiàn):

引入依賴

  1. <dependency> 
  2.     <groupId>org.redisson</groupId> 
  3.     <artifactId>redisson</artifactId> 
  4.     <version>3.13.1</version> 
  5. </dependency> 

Redisson配置文件:

  1. @Bean 
  2. public RedissonClient redissonClient() { 
  3.     Config config = new Config(); 
  4.     config.useClusterServers() 
  5.             .setScanInterval(3000) // 集群狀態(tài)掃描間隔時間,單位是毫秒 
  6.             .addNodeAddress("redis://192.168.0.1:6379).setPassword("666") 
  7.             .addNodeAddress("redis://192.168.0.2:6379").setPassword("666"
  8.             .addNodeAddress("redis://192.168.0.3:6379"
  9.             .setPassword("666"); 
  10.     return Redisson.create(config); 

獲取鎖操作:

  1. long waitTimeout = 10; 
  2. long leaseTime = 1; 
  3. RLock lock1 = redissonClient1.getLock("lock1"); 
  4. RLock lock2 = redissonClient2.getLock("lock2"); 
  5. RLock lock3 = redissonClient3.getLock("lock3"); 
  6.  
  7. RedissonRedLock redLock = new RedissonRedLock(lock1, lock2, lock3); 
  8.  
  9. redLock.trylock(waitTimeout,leaseTime,TimeUnit.SECONDS); 
  10. try{ 
  11.     //... 
  12. }finally{ 
  13.     redLock.unlock(); 

總結

實現(xiàn)分布式鎖的方式不止這三種,最簡單的就是數(shù)據(jù)庫實現(xiàn),Zookeeper實現(xiàn)也相對比較簡單,但是性能最好的還是Redis實現(xiàn),但是可靠性方面,Zookeeper基于分布式集群,具有天然的優(yōu)勢,可靠性相對更高。如果業(yè)務場景對性能要求不是很高的時候,優(yōu)先使用Zookeeper實現(xiàn)分布式鎖。

 

責任編輯:武曉燕 來源: 故里學Java
相關推薦

2020-12-15 06:57:24

java服務器

2020-04-10 08:03:04

分布式鎖Redlock算法流行算法

2019-06-19 15:40:06

分布式鎖RedisJava

2024-07-15 08:25:07

2018-07-17 08:14:22

分布式分布式鎖方位

2022-08-04 08:45:50

Redisson分布式鎖工具

2019-02-26 09:51:52

分布式鎖RedisZookeeper

2021-07-16 07:57:34

ZooKeeperCurator源碼

2018-11-27 16:17:13

分布式Tomcat

2021-11-26 06:43:19

Java分布式

2020-07-06 14:53:24

分布式鎖系統(tǒng)單機鎖

2023-09-22 08:00:00

分布式鎖Redis

2022-01-06 10:58:07

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

2023-08-21 19:10:34

Redis分布式

2021-10-25 10:21:59

ZK分布式鎖ZooKeeper

2017-10-24 11:28:23

Zookeeper分布式鎖架構

2021-07-06 08:37:29

Redisson分布式

2018-01-30 09:07:36

Ceph分布式存儲

2024-11-28 15:11:28

2020-06-15 08:15:47

分布式鎖系統(tǒng)
點贊
收藏

51CTO技術棧公眾號