Sentinel底層LongAdder的計數實現

2021-10-13 14:21:15 字數 2114 閱讀 4484

本文的github位址

在 longadder 中,底層通過多個數值進行累加來得到最後的結果。當多個執行緒對同乙個 longadder 進行更新的時候,將會對這一些列的集合進行動態更新,以避免多執行緒之間的資源競爭。當需要得到 longadder 的具體的值的時候,將會將一系列的值進行求和作為最後的結果。

在高併發的競爭下進行類似指標資料的收集的時候,longadder 通常會和 atomiclong 進行比較,在低競爭的場景下,兩者有著相似的效能表現。而當在高併發競爭的場景下,longadder 將會表現更高的效能,但是也會伴隨更高的記憶體消耗。

transient

volatile cell[

] cells;

transient

volatile

long base;

cells 是乙個簡單的 cell 陣列,當比如通過 longadder 的 add()方法進行 longadder 內部的資料的更新的時候,將會根據每個執行緒的乙個 hash 值與 cells 陣列的長度進行取模而定位,並在定位上的位置進行資料更新。而 base 則是當針對 longadder 的資料的更新時,並沒有執行緒競爭的時候,將會直接更新在 base 上,而不需要前面提到的 hash 再定位過程,當 longadder 的 sum()方法被呼叫的時候,將會對 cells 的所有資料進行累加在加上 sum 的值進行返回。

public

long

sum()}

}return sum;

}

相比 sum()方法,longadder 的 add()方法要複雜得多。

public

void

add(

long x)

}}

在 add()方法的一開始,將會觀察 cells 陣列是否存在,如果不存在,將會嘗試直接通過 casbase()方法在 base 上通過 cas 更新,這是在低併發競爭下的 add()流程,這一流程的前提是對於 longadder 的更新並沒有遭遇別的執行緒的併發修改。

在當 cells 已經存在,而或者對於 base 的 cas 更新失敗,都將會將資料的更新落在 cells 陣列之上。首先,每個執行緒都會在其 threadlocal 中生成乙個執行緒專有的隨機數,並根據這個隨機數與 cells 進行取模,定位到的位置進行 cas 修改。在這個流程下,由於根據執行緒專有的隨機數進行 hash 而定位的流程,盡可能的避免了執行緒間的資源競爭。但是仍舊可能存在 hash 碰撞而導致兩個執行緒定位到了同乙個 cells 槽位的情況,這裡就需要通過 retryupdate()方法進行進一步的解決。

retryupdate()方法的**很長,但是邏輯很清晰,主要分為一下幾個流程,其中的主流程是乙個死迴圈,進入 retryupdate()方法後,將會不斷嘗試執行主要邏輯,直到對應的邏輯執行完畢:

1.當進入 retryupdate()的時候,cells 陣列還沒有建立,將會嘗試獲取鎖並初始化 cells 陣列並直接在 cells 陣列上進行修改,而別的執行緒在沒建立的情況下進入並獲取鎖失敗,將會直接嘗試在 base 上進行更行。 2.當進入 retryupdate()的時候,cells 陣列已經建立,但是分配給其的陣列槽位的 cells 還沒有進行初始化,那麼將會嘗試獲取鎖並對該槽位進行初始化。 3.當進入 retryupdate()的時候,cells 陣列已經建立,分配給其的槽位的 cell 也已經完成了初始化,而是因為所定位到的槽位與別的執行緒發生了 hash 碰撞,那麼將會加鎖並擴容 cells 陣列,之後對該執行緒持有的 hash 進行 rehash,在下一輪迴圈中對新定位的槽位資料進行更新。而別的執行緒在嘗試擴容並獲取鎖失敗的時候,將會直接對自己 rehash 並在下一輪的迴圈中重新在新的 cells 陣列中進行定位更新。

最後,提一下 cells 陣列中的 cell 物件。

volatile

long p0, p1, p2, p3, p4, p5, p6;

volatile

long value;

volatile

long q0, q1, q2, q3, q4, q5, q6;

每個 cell 物件中具體存放的 value 前後都由 7 個 long 型別的字段進行記憶體填充以避免快取行偽共享而導致的快取失效。

Sentinel衛星資料

哨兵 系列衛星是歐洲哥白尼 copernicus 計畫 之前稱為 全球環境與安全監測 gmes 計畫 空間部分 gsc 的專用衛星系列,由歐洲委員會 ec 投資,歐洲航天局 esa 研製。哨兵 系列衛星主要包括2顆哨兵 1衛星 2顆哨兵 2衛星 2顆哨兵 3衛星 2個哨兵 4載荷 2個哨兵 5載荷 ...

sentinel服務限流

一 qps限流 直接拒絕方式是預設的流量控制方式,當qps超過任意規則的閾值後,新的請求就會被立即拒絕,拒絕方式為丟擲flowexception 二 warm up warm up方式,即預熱 冷啟動方式。當系統長期處於低水位的情況下,當流量突然增加時,直接把系統拉公升到高水位可能瞬間把系統壓垮。通...

sentinel系統規則

load 自適應 僅對 linux unix like 機器生效 系統的 load1 作為啟發指標,進行自適應系統保護。當系統 load1 超過設定的啟發值,且系統當前的併發執行緒數超過估算的系統容量時才會觸發系統保護 bbr 階段 系統容量由系統的 maxqps minrt 估算得出。設定參考值一...