Jedis詳解 Cluster連線建立與關閉

2021-10-03 07:04:31 字數 4813 閱讀 8149

使用jedis操作redis cluster,我們需要建立jediscluster物件,再通過jediscluster物件例項運算元據,**一般如下:

// 初始化所有節點(例如6個節點)

setjedisclusternode = new hashset() };

// 初始化commnon-pool連線池,並設定相關引數

genericobjectpoolconfig poolconfig = new genericobjectpoolconfig();

// 初始化jediscluster

jediscluster jediscluster = new jediscluster(jedisclusternode, 1000, 1000, 5, poolconfig);

下面我們詳細了解下jediscluster的建立邏輯,其建構函式核心功能為建立connectionhandler例項,jedisclusterconnectionhandler的建構函式如下:

public jedisclusterconnectionhandler(setnodes,

final genericobjectpoolconfig poolconfig, int connectiontimeout,

int sotimeout, string password, string clientname,

boolean ssl, sslsocketfactory sslsocketfactory, sslparameters sslparameters,

hostnameverifier hostnameverifier, jedisclusterhostandportmap portmap)

其中重點需要關注的是initializeslotscache方法,該方法主要初始化集群中槽和節點的對映關係,下面簡單介紹下redis cluster的資料分割槽和路由方案。

redis cluster使用虛擬槽資料分割槽方案,每個節點維護部分槽和資料,當需要讀取資料時,使用"crc16(key) & 16383"雜湊演算法得到key所在的槽,redis cluster本身會維護節點和槽的資訊。

當你使用dummy型客戶端(例如redis-cli)在某個不具備該槽的節點上執行讀取指令時,redis cluster會返回"moved"重定向資訊,告訴我們該槽所在節點的ip和埠資訊,然後就可以到相應的節點上執行命令讀取資料。該型別的客戶端需要我們自行進行重定向操作,相對不方便。

而jedis等smart型客戶端本身就維護了槽和節點的對映關係,通過"crc16(key) & 16383"雜湊演算法得到key所在的槽後,就可以通過對映關係找到對應的節點,然後直接給該節點傳送指令返回資料。

下面為initializeslotscache方法原始碼:

private void initializeslotscache(setstartnodes,

int connectiontimeout, int sotimeout, string password, string clientname,

boolean ssl, sslsocketfactory sslsocketfactory, sslparameters sslparameters, hostnameverifier hostnameverifier)

if (clientname != null)

cache.discoverclusternodesandslots(jedis);

break;

} catch (jedisconnectionexception e) finally

}}}

需要注意的是,由於discoverclusternodesandslots內使用了writelock寫鎖,因此保證了只有乙個連線會初始化節點和槽的對映關係。

重點分析下discoverclusternodesandslots方法:

public void discoverclusternodesandslots(jedis jedis) 

//解析出所負責的的所有槽

listslotnums = getassignedslotarray(slotinfo);

// hostinfos

/*** 解析主節點和從節點資訊,構建槽和節點的對映關係:

* 1. 新增nodes元素,key為":",value為該節點對應的jedispool連線池

* 2. 新增slots元素,key為"slotnum",value為該槽對應節點的jedispool連線池

*/int size = slotinfo.size();

for (int i = master_node_index; i < size; i++)

//獲取節點ip埠資訊

hostandport targetnode = generatehostandport(hostinfos);

//設定nodes,map.entry結構為//從節點和主節點都會進行儲存

setupnodeifnotexist(targetnode);

if (i == master_node_index) }}

} finally

}

維護節點和槽的對映關係主要通過jedisclusterinfocache裡面的兩個map型別的變數:

private final map nodes = new hashmap();

private final map slots = new hashmap();

該方法的主要流程如下:

1. 清空nodes和slots資料,並關閉關聯的jedispool。

2. 使用"cluster slots"指令獲取cluster節點和槽的對映關係,其返回結構如下:

127.0.0.1:6379> cluster slots

1) 1) (integer) 5462 . -- 起始槽

2) (integer) 10922 . -- 終止槽

3) 1) "127.0.0.1" . -- 主節點ip

2) (integer) 6380 -- 主節點埠

3) "85371dd3c2c11dbb1cd506ed028de10bb7fa2816" -- 主節點runid

4) 1) "127.0.0.1" . -- 從節點ip

2) (integer) 6383 -- 從節點埠

3) "01740d2eb2c9f89014e2b8b673d444753d0685cd" -- 從節點runid

2) 1) (integer) 10923

2) (integer) 16383

3) 1) "127.0.0.1"

2) (integer) 6381

3) "aacad0a5a2b37d4e11f2253849263575adb78740"

4) 1) "127.0.0.1"

2) (integer) 6384

3) "5e099198bba08597d695f6e2e3db2d6ec1494534"

3) 1) (integer) 0

2) (integer) 5461

3) 1) "127.0.0.1"

2) (integer) 6379

3) "672cc8350bb1ac1d94e9c511ea234f6b7f86cab1"

4) 1) "127.0.0.1"

2) (integer) 6382

3) "6bab67c3619c4b9cbdfd247ff3e446308a0c6326"

3. 解析出所負責的的所有槽,**如下:

private listgetassignedslotarray(listslotinfo) 

return slotnums;

}

slotnums的數量即為該主節點所負責的槽的數量。

4. 解析主節點和從節點資訊,構建槽和節點的對映關係。

值得注意的是,nodes裡面會儲存主節點和從節點的資訊,但是slots裡面槽只對應主節點的連線池jedispool,從節點並需要設定。

最後值得一提的是,jedis連線sentinel時,連線的是sentinel集群,通過「mastername」引數獲取sentinel集群監控的主節點連線,後續的操作也是通過該主節點連線執行。但連線cluster時,其實連線的是每個redis例項,讀取資料時會根據jedis維護的槽和節點對映關係去對應的節點上讀取。

jediscluster關閉**如下:

jediscluster.close();

其關閉原始碼邏輯主要呼叫jedisclusterinfocache類的reset方法,該方法關閉了所有集群節點的連線,並將nodes和slots資料清空。

//binaryjediscluster類

@override

public void close()

}//jedisclusterconnectionhandler類

@override

public void close()

//jedisclusterinfocache類

public void reset()

} catch (exception e)

}nodes.clear();

slots.clear();

} finally

}

Jedis事務詳解

1 正常執行的事務 編碼測試 package com.haiyang import com.alibaba.fastjson.jsonobject import redis.clients.jedis.jedis import redis.clients.jedis.transaction publ...

jedis操作詳解 List

在redis 中,list 型別是按照插入順序排序的字串鍊錶。和資料結構中的普通鍊錶一樣,我們可以在其頭部 left 和尾部 right 新增新的元素。在插入時,如果該鍵並不存在,redis 將為該鍵建立乙個新的鍊錶。與此相反,如果鍊錶中所有的元素均被移除,那麼該鍵也將會被從資料庫中刪除。list ...

jedis 連線池配置詳解

最大活動物件數 redis.pool.maxtotal 1000 最大能夠保持idel狀態的物件數 redis.pool.maxidle 100 最小能夠保持idel狀態的物件數 redis.pool.minidle 50 當池內沒有返回物件時,最大等待時間 redis.pool.maxwaitmi...