版權所有,轉載請註明原文鏈接。
谷歌的go-redis@v6.15.7對redis cluster集羣提供了支持,這也是相對於redigo的一個重要優勢,後者目前還沒有提供集羣支持。go-redis@v6.15.7的主要功能點如下:
1.客戶端緩存了每一組連續的slot所對應的起止slotID和存儲節點列表,以提高一次性訪問的成功率,避免MOVED重定向。
type clusterSlot struct {
start, end int
nodes []*clusterNode
}
2.如果執行命令時服務端返回MOVED錯誤,則客戶端通過cluster slots命令重新獲取節點信息
//如果是MOVED類型錯誤,則更新節點信息
func (c *ClusterClient) checkMovedErr(
cmd Cmder, err error, failedCmds *cmdsMap,
) bool {
moved, ask, addr := internal.IsMovedError(err)
if moved {
c.state.LazyReload()
...
//向節點發送CLUSTER SLOTS命令
func (c *ClusterClient) loadState() (*clusterState, error) {
...
slots, err := node.Client.ClusterSlots().Result()
...
3. 管理一組redis.Client,每一個redis.Client獨立創建一個連接池。
4. 對key執行命令時,先計算key通過CRC16轉換後的值然後用16384取餘,從而得到一個0-16383的slotID。然後找到對應的主從節點列表,列表第一個元素是主節點。
//通過二分查找來找到slotID對應的節點列表
func (c *clusterState) slotNodes(slot int) []*clusterNode {
i := sort.Search(len(c.slots), func(i int) bool {
return c.slots[i].end >= slot
})
if i >= len(c.slots) {
return nil
}
x := c.slots[i]
if slot >= x.start && slot <= x.end {
return x.nodes
}
return nil
}
5. 可以通過配置來指定只讀操作是否可以在從節點上執行,還可以進一步指定在多個從節點之間隨機選取或者按Ping時間最短來選取。其中Ping命令是另起一個go routine來計算,Ping 10次求平均。
//10次Ping求平均
func (n *clusterNode) updateLatency() {
const probes = 10
var latency uint32
for i := 0; i < probes; i++ {
start := time.Now()
n.Client.Ping()
probe := uint32(time.Since(start) / time.Microsecond)
latency = (latency + probe) / 2
}
atomic.StoreUint32(&n.latency, latency)
}
6. 批量執行多條命令時,客戶端先計算各條命令對應的slotID,然後把slotID相同的命令放到一起發送給對應節點批量執行,不同slotID之間是並行執行的。在計算slotID時,採用的是每條命令的第一個key,也就是說含有多個key的命令有可能會導致MOVED重定向,從而影響效率。
//取第一個key計算slotID
func cmdSlot(cmd Cmder, pos int) int {
if pos == 0 {
return hashtag.RandomSlot()
}
firstKey := cmd.stringArg(pos)
return hashtag.Slot(firstKey)
}
7. 經驗證,可以支持在客戶端redis寫操作達到1000QPS負載的情況下,動態增加節點,期間性能幾乎沒有什麼影響。(服務端5.0.8,客戶端 v6.15.7)。因爲,集羣每次只是移動16384個slot中的一個,而被移動的slot也只是造成客戶端多一次MOVED重定向,所以總體性能影響很小。
8. 經驗證,可以支持在客戶端redis寫操作達到1000QPS負載的情況下,人爲掛掉一個主節點,則集羣自動切換主從,客戶端自動更新節點信息表,期間性能幾乎沒有什麼影響,客戶端也沒有出現報錯。(服務端5.0.8,客戶端 v6.15.7)。
9. 啓動時不會建立到節點的連接,在需要執行命令時才建立連接。
相關文章: