Eureka 源碼解析 —— Eureka源碼解析 —— 應用實例註冊發現 (九)之歲月是把萌萌的讀寫鎖

摘要: 原創出處 http://www.iocoder.cn/Eureka/instance-registry-read-write-lock/ 「芋道源碼」歡迎轉載,保留摘要,謝謝!



1. 概述

本文主要分享 Eureka 註冊中心的那把讀寫鎖,讓我瘙癢難耐,卻不得其解。在某次意外的摳腳的一刻( 筆者不抽菸,如果抽菸的話,此處應該就不是摳腳了 ),突然頓悟,爽,這好比… 比喻有點猥瑣,筆者就省略 100 字。

不瞎比比,上代碼:

public abstract class AbstractInstanceRegistry implements InstanceRegistry {
private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private final Lock read = readWriteLock.readLock();
private final Lock write = readWriteLock.writeLock();
// ... 省略其他代碼
}

推薦 Spring Cloud 書籍

2. 讀寫鎖

我們把設計到讀寫鎖的方法整理如下:

方法 讀鎖 寫鎖 不使用
#register(...)
#cancel(...)
#evict(...)
#renew(...)
#statusUpdate(...)
#deleteStatusOverride(...)
#getApplicationDeltasFromMultipleRegions(...)
#getApplicationsFromMultipleRegions(...)

是否看到這讀寫感到几絲詭異的味道?OK,我們把問題梳理如下:

  • A. 爲什麼 #register(...) / #cancel(...) / #evict(...) / #statusUpdate(...) / #deleteStatusOverride(...)寫操作使用讀鎖
  • B. 爲什麼 #renew(...) 寫操作不使用
  • C. 爲什麼 #getApplicationDeltasFromMultipleRegions(...) 讀操作使用寫鎖
  • D. 爲什麼 getApplicationsFromMultipleRegions(...) 讀操作不使用

先解釋 A + C

我們來回想下,在 Eureka 應用集合一致性哈希碼的公式:appsHashCode = ${status}_${count}_ 。( 不瞭解的同學可以加載下 《Eureka 源碼解析 —— 應用實例註冊發現(七)之增量獲取》「 2. 應用集合一致性哈希碼 」 )

應用實例的數量和狀態都會影響哈希碼的計算結果。也就是說,上述前六個( 包括不使用鎖的 #renew(...) 方法 )方法的調用都會影響哈希碼。

我們把目光移向唯一使用寫鎖#getApplicationDeltasFromMultipleRegions(...) 方法,該方法執行過程中,需要保證 recentlyChangedQueueregistry 共享變量的應用實例的狀態一致,不然返回的增量應用實例集合的狀態是不準確的。此時能夠達到該效果,必須讓 #getApplicationDeltasFromMultipleRegions(...) 和前六個方法互斥。方案如下:

  • a. 全部 synchronized
  • b. #getApplicationDeltasFromMultipleRegions(...) 使用讀鎖,前六個方法使用寫鎖
  • c. #getApplicationDeltasFromMultipleRegions(...) 使用寫鎖,前六個方法使用讀鎖

Eureka 選擇了方案c,原因如下:


再解釋 D

#getApplicationsFromMultipleRegions(...) 方法的邏輯,只依賴 registry 共享變量,不存在應用實例的狀態一致的困擾,所以不使用鎖。


最後解釋 B

#renew(...) 方法的邏輯,雖然會影響應用實例的狀態,但是是極小概率,考慮到它調用的比較頻繁,比起因爲鎖給這個方法帶來的性能降低,不如返回的結果暫時不夠準確。( 想了解極小概率發生原因的同學可以加載 《Eureka 源碼解析 —— 應用實例註冊發現(八)之覆蓋狀態》「 4.3 續租場景 」 )


TODO [0029] 讀寫鎖

筆者路上突然又想了問題,可能不是上述原因,可能和 ResponseCache 有關係,參見 #invalidateCache(...) 方法的每次調用。也就是說,這個讀寫鎖是針對 ResponseCache 的讀寫鎖。

666. 彩蛋

開森 !

本來以爲需要跟 Eureka 官方提交 issue 提問,並且做好了獲得不到答案的準備,結果無意中的摳腳( 請允許我熱愛摳腳給我帶來的靈感 )解答了自己的疑惑。

歲月是把糾結而又萌萌噠的鎖,你不知道你的困擾,哪天不經意的被打開。

願大喜大悲,不枉僅知的這一生。

發佈了22 篇原創文章 · 獲贊 2 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章