一致性hash在 redis中應用

2021-08-28 00:09:00 字數 3287 閱讀 8519

首先我們來看一下shardedjedis的乙個繼承關係

看完了圖,那麼我們一步一步跟著我們的**呼叫來看,以我們最簡單的shardedjedis.get(key)方法為例:

public string get(string key)
這邊有呼叫乙個getshard方法,引數為我們傳入的key,然後返回乙個普通的jedis物件,那麼這個getshard是用來做什麼的呢,大家可能已經猜到了,這個方法就是會根據我們傳入的key做一致性雜湊判斷,然後返回key落到的那個redis例項上的乙個redis連線,不同的key返回的redis連線可能是不同的。

進入getshard方法,你會發現這個實現是在sharded類中實現的(看上面的類圖可以發現頂層的sharded類),**如下:

public r getshard(string key) 

public s getshardinfo(byte key)

return tail.get(tail.firstkey());

} public s getshardinfo(string key)

上面的方法是層層呼叫的關係,在這邊不細說,我們主要看下第二個方法(getshardinfo(byte key))實現(上面的nodes變數是乙個treemap型別,algohashing型別,即key分片所使用的hash演算法,這個在前一篇有簡單說過),那麼這段**的含義我們大概成猜出來了,

就是在乙個treemap中取出大於等於key之後的部分檢視sortmap

在sortmap取得第乙個鍵值對的值,然後返回乙個s物件,

然後根據這個s物件,去resources(resources = new linkedhashmap, r>())中get乙個r物件

那麼這個s、r物件各自代表什麼呢?看下面的**

public class sharded>
public class binaryshardedjedis extends shardedimplements

binaryjediscommands

可以得出s= jedisshardinfo,r= jedis 物件,即在treemap儲存了伺服器劃分的虛擬節點的資訊,linkedhashmap中儲存了伺服器的物理連線。 

jedisshardinfo具體資訊如下:裡面包含了jedis伺服器的一些資訊,最重要的是它的父類中有乙個weight欄位,作為本jedis伺服器的權值。

ok,那我們了解了實際上就是根據jedis伺服器的資訊去獲取乙個jedis的連線,返回給上層呼叫。

我們可以梳理下這個邏輯:

當我們使用shardedjedis去查乙個key時,首先它會把這個key進行乙個hash演算法

根據這個hash值然後去treemap中,查出這個key落在哪個例項中,並返回redis例項對應的具體資訊

根據這個redis的例項資訊,到乙個儲存jedis鏈結和例項資訊對應關係的linkedhashmap中找到這個jedis連線

最終返回jedis連線,執行物件的命令操作(到這步後實際上和單機操作一樣了)

那麼我們的nodes伺服器虛擬節點和resources伺服器物理連線是什麼時候初始化的呢,接下來繼續看

我們繼續看sharded的構造方法

public sharded(listshards, hashing algo) 

public sharded(listshards, hashing algo, pattern tagpattern)

這邊有乙個initialize方法,就是用來對虛擬節點和物理連線進行初始化的,看其實現

private void initialize(listshards) 

else for (int n = 0; n < 160 * shardinfo.getweight(); n++)

resources.put(shardinfo, shardinfo.createresource());}}

具體細節就不說了,根據上面的,我們就知道是在這邊進行了初始化,將每台伺服器節點採用hash演算法劃分為160個虛擬節點(可以配置劃分權重),儲存在treemap中,

然後把每台伺服器節點的資訊和物理連線以鍵值對儲存linkedhashmap中。

然後通過一系列的查詢,發現sharded的構造方法其實是在我們jedispool.getresource()時就完成的

//初始化shardedjedispool

listinfolist = arrays.aslist(shardinfo1, shardinfo2, shardinfo3);

shardedjedispool jedispool = new shardedjedispool(poolconfig, infolist);

shardedjedis jedis = jedispool.getresource();

納尼? 每次jedispool.getresource()才初始化?那會不會造成很慢呢,其實不用擔心,其底層是使用了commons.pool來進行連線池的一些操作,會根據我們配置的連線池引數來生成對應的連線並儲存,其中的細節很複雜,博主沒有繼續深究,實現其實和資料庫連線池是一致的。

shardedjedis分布式具體的的實現思路:

**:

Redis 一致性Hash演算法

在redis 集群模式cluster中,redis採用的是分片sharding的方式,也就是將資料採用一定的分割槽策略,分發到相應的集群節點中。但是我們使用上述hash演算法進行快取時,會出現一些缺陷,主要體現在伺服器數量變動的時候,所有快取的位置都要發生改變!具體來講就是說第一當快取伺服器數量發生...

一致性hash演算法 面試必備 一致性hash演算法

最近公司在招人,我們準備的問題中有一道是關於一致性hash演算法的問題,只有一些面試者能夠回答上來,而且答的也不是很全面,有的面試者只是聽說過,有的連聽都沒聽過,下面我把一致性hash演算法整理一下分享給大家 一致性雜湊演算法在1997年由麻省理工學院的karger等人在解決分布式cache中提出的...

一致性hash演算法虛擬節點 一致性hash演算法

hash 演算法也叫做雜湊演算法,他可以讓任意長度的資料m對映成為長度固定的值h。hash演算法的第乙個作用就是資料的快速儲存與查詢。寫過程式的人都知道,基本上主流的程式語言裡面都有個資料結構叫做map dictionary或者 hash table 它是根據key來直接訪問結果的資料結構。key的...