成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

字節二面:Redis cluster集群原理,客戶端是怎樣知道該訪問哪個分片的

開發 前端
哨兵模式基于主從模式,實現讀寫分離,它還可以自動切換,系統可用性更高。但是它每個節點存儲的數據是一樣的,浪費內存,并且不好在線擴容。

前言

大家好,我是田螺。

有位伙伴面試了字節,說有道題,他當時答不上,大家一起來看看:redis的cluster集群原理,客戶端是怎樣知道該訪問哪個分片的。

我們應該怎樣更好回答呢?可以分這幾個維度

  • 為什么需要Redis Cluster?哨兵模式不香嗎?
  • 客戶端是怎樣知道該訪問哪個分片的? (哈希槽)
  • redis實例上并沒有相應的數據,會怎么樣?(MOVED重定向和ASK重定向)
  • 各個節點之間是怎么通信的呢(Gossip協議)
  • 集群內節點出現故障怎么辦(故障轉移)
  • 加餐:Redis Cluster的Hash Slot 為什么是16384?

1. 為什么需要Redis Cluster?

哨兵模式基于主從模式,實現讀寫分離,它還可以自動切換,系統可用性更高。但是它每個節點存儲的數據是一樣的,浪費內存,并且不好在線擴容。

因此,Reids Cluster集群(切片集群的實現方案)應運而生,它在Redis3.0加入的,實現了Redis的分布式存儲。對數據進行分片,也就是說每臺Redis節點上存儲不同的內容,來解決在線擴容的問題。并且,它可以保存大量數據,即分散數據到各個Redis實例,還提供復制和故障轉移的功能。

比如你一個Redis實例保存15G甚至更大的數據,響應就會很慢,這是因為Redis RDB 持久化機制導致的,Redis會fork子進程完成 RDB 持久化操作,fork執行的耗時與 Redis 數據量成正相關。

這時候你很容易想到,把15G數據分散來存儲就好了嘛。這就是Redis切片集群的初衷。切片集群是啥呢?來看個例子,如果你要用Redis保存15G的數據,可以用單實例Redis,或者3臺Redis實例組成切片集群,對比如下:

切片集群和Redis Cluster的區別:Redis Cluster是從Redis3.0版本開始,官方提供的一種實現切片集群的方案。

圖片圖片

既然數據是分片分布到不同Redis實例的,那客戶端到底是怎么確定想要訪問的數據在哪個實例上呢?我們一起來看下Reids Cluster是怎么做的哈。

2. 客戶端是怎樣知道該訪問哪個分片的?哈希槽

Redis Cluster方案采用哈希槽(Hash Slot),來處理數據和實例之間的映射關系。

一個切片集群被分為16384個slot(槽),每個進入Redis的鍵值對,根據key進行散列,分配到這16384插槽中的一個。使用的哈希映射也比較簡單,用CRC16算法計算出一個16bit的值,再對16384取模。數據庫中的每個鍵都屬于這16384個槽的其中一個,集群中的每個節點都可以處理這16384個槽。

集群中的每個節點負責一部分的哈希槽,假設當前集群有A、B、C3個節點,每個節點上負責的哈希槽數 =16384/3,那么可能存在的一種分配:

  • 節點A負責0~5460號哈希槽
  • 節點B負責5461~10922號哈希槽
  • 節點C負責10923~16383號哈希槽

客戶端給一個Redis實例發送數據讀寫操作時,如果這個實例上并沒有相應的數據,會怎么樣呢?MOVED重定向和ASK重定向了解一下哈

3. 實例上并沒有相應的數據,會怎么樣?(MOVED重定向和ASK重定向)

在Redis cluster模式下,節點對請求的處理過程如下:

  • 通過哈希槽映射,檢查當前Redis key是否存在當前節點
  • 若哈希槽不是由自身節點負責,就返回MOVED重定向
  • 若哈希槽確實由自身負責,且key在slot中,則返回該key對應結果
  • 若Redis key不存在此哈希槽中,檢查該哈希槽是否正在遷出(MIGRATING)?
  • 若Redis key正在遷出,返回ASK錯誤重定向客戶端到遷移的目的服務器上
  • 若哈希槽未遷出,檢查哈希槽是否導入中?
  • 若哈希槽導入中且有ASKING標記,則直接操作,否則返回MOVED重定向

3.1 Moved 重定向

客戶端給一個Redis實例發送數據讀寫操作時,如果計算出來的槽不是在該節點上,這時候它會返回MOVED重定向錯誤,MOVED重定向錯誤中,會將哈希槽所在的新實例的IP和port端口帶回去。這就是Redis Cluster的MOVED重定向機制。流程圖如下:

圖片圖片

3.2 ASK 重定向

Ask重定向一般發生于集群伸縮的時候。集群伸縮會導致槽遷移,當我們去源節點訪問時,此時數據已經可能已經遷移到了目標節點,使用Ask重定向可以解決此種情況。

圖片圖片

4. 各個節點之間是怎么通信的呢(Gossip)

一個Redis集群由多個節點組成,各個節點之間是怎么通信的呢?通過Gossip協議!Gossip是一種謠言傳播協議,每個節點周期性地從節點列表中選擇 k 個節點,將本節點存儲的信息傳播出去,直到所有節點信息一致,即算法收斂了。

Gossip協議基本思想:一個節點想要分享一些信息給網絡中的其他的一些節點。于是,它周期性的隨機選擇一些節點,并把信息傳遞給這些節點。這些收到信息的節點接下來會做同樣的事情,即把這些信息傳遞給其他一些隨機選擇的節點。一般而言,信息會周期性的傳遞給N個目標節點,而不只是一個。這個N被稱為fanout

Redis Cluster集群通過Gossip協議進行通信,節點之前不斷交換信息,交換的信息內容包括節點出現故障、新節點加入、主從節點變更信息、slot信息等等。gossip協議包含多種消息類型,包括ping,pong,meet,fail等等

圖片圖片

  • meet消息:通知新節點加入。消息發送者通知接收者加入到當前集群,meet消息通信正常完成后,接收節點會加入到集群中并進行周期性的ping、pong消息交換。
  • ping消息:節點每秒會向集群中其他節點發送 ping 消息,消息中帶有自己已知的兩個節點的地址、槽、狀態信息、最后一次通信時間等
  • pong消息:當接收到ping、meet消息時,作為響應消息回復給發送方確認消息正常通信。消息中同樣帶有自己已知的兩個節點信息。
  • fail消息:當節點判定集群內另一個節點下線時,會向集群內廣播一個fail消息,其他節點接收到fail消息之后把對應節點更新為下線狀態。

特別的,每個節點是通過集群總線(cluster bus) 與其他的節點進行通信的。通訊時,使用特殊的端口號,即對外服務端口號加10000。例如如果某個node的端口號是6379,那么它與其它nodes通信的端口號是 16379。nodes 之間的通信采用特殊的二進制協議。

5. 集群內節點出現故障怎么辦(故障轉移)

Redis集群實現了高可用,當集群內節點出現故障時,通過故障轉移,以保證集群正常對外提供服務。

redis集群通過ping/pong消息,實現故障發現。這個環境包括主觀下線和客觀下線。

  • 主觀下線:某個節點認為另一個節點不可用,即下線狀態,這個狀態并不是最終的故障判定,只能代表一個節點的意見,可能存在誤判情況。

圖片圖片

  • 客觀下線:指標記一個節點真正的下線,集群內多個節點都認為該節點不可用,從而達成共識的結果。如果是持有槽的主節點故障,需要為該節點進行故障轉移。
  • 假如節點A標記節點B為主觀下線,一段時間后,節點A通過消息把節點B的狀態發到其它節點,當節點C接受到消息并解析出消息體時,如果發現節點B的pfail狀態時,會觸發客觀下線流程;
  • 當下線為主節點時,此時Redis Cluster集群為統計持有槽的主節點投票,看投票數是否達到一半,當下線報告統計數大于一半時,被標記為客觀下線狀態。

 流程如下:

圖片圖片

  • 故障恢復:故障發現后,如果下線節點的是主節點,則需要在它的從節點中選一個替換它,以保證集群的高可用。流程如下:

圖片圖片

  • 資格檢查:檢查從節點是否具備替換故障主節點的條件。
  • 準備選舉時間:資格檢查通過后,更新觸發故障選舉時間。
  • 發起選舉:到了故障選舉時間,進行選舉。
  • 選舉投票:只有持有槽的主節點才有票,從節點收集到足夠的選票(大于一半),觸發替換主節點操

6. 加餐:為什么Redis Cluster的Hash Slot 是16384?

對于客戶端請求過來的鍵值key,哈希槽=CRC16(key) % 16384,CRC16算法產生的哈希值是16bit的,按道理該算法是可以產生2^16=65536個值,為什么不用65536,用的是16384(2^14)呢?

大家可以看下作者的原始回答:

圖片圖片

Redis 每個實例節點上都保存對應有哪些slots,它是一個unsigned char slots[REDIS_CLUSTER_SLOTS/8]類型

圖片圖片

  • 在redis節點發送心跳包時需要把所有的槽放到這個心跳包里,如果slots數量是65536,占空間= 65536 / 8(一個字節8bit) / 1024(1024個字節1kB) =8kB,如果使用slots數量是16384,所占空間 =16384 / 8(每個字節8bit) / 1024(1024個字節1kB) = 2kB,可見16384個slots比 65536省 6kB內存左右,假如一個集群有100個節點,那每個實例里就省了600kB啦
  • 一般情況下Redis cluster集群主節點數量基本不可能超過1000個,超過1000會導致網絡擁堵。對于節點數在1000以內的Redis cluster集群,16384個槽位其實夠用了。

既然為了節省內存網絡開銷,為什么 slots不選擇用8192(即16384/2)呢?

8192 / 8(每個字節8bit) / 1024(1024個字節1kB) = 1kB,只需要1KB!可以先看下Redis 把 Key 換算成所屬 slots 的方法

unsignedintkeyHashSlot(char*key,intkeylen){
ints,e;/*start-endindexesof{and}*/

for(s=0;s<keylen;s++)
if(key[s]=='{')break;

/*No'{'?Hashthewholekey.Thisisthebasecase.*/
if(s==keylen)returncrc16(key,keylen)&0x3FFF;

/*'{'found?Checkifwehavethecorresponding'}'.*/
for(e=s+1;e<keylen;e++)
if(key[e]=='}')break;

/*No'}'ornothingbetweeen{}?Hashthewholekey.*/
if(e==keylen||e==s+1)returncrc16(key,keylen)&0x3FFF;

/*Ifweareherethereisbotha{anda}onitsright.Hash
*whatisinthemiddlebetween{and}.*/
returncrc16(key+s+1,e-s-1)&0x3FFF;
}

Redis 將key換算成slots 的方法:其實就是是將crc16(key) 之后再和slots的數量進行與計算

這里為什么用0x3FFF(16383)來計算,而不是16384呢?因為在不產生溢出的情況下x % (2^n)等價于x & (2^n - 1)即x % 16384 == x & 16383

那到底為什么不用8192呢?

crc16 出來結果,理論上出現重復的概率為 1?65536,但實際結果重復概率可能比這個大不少,就像crc32 結果 理論上 1/40億 分之一,但實際有人測下來10萬碰撞的概率就比較大了。假如 slots 設置成 8192, 200個實例的節點情況下,理論值是 每40個不同key請求,命中就會失效一次,假如節點數增加到400,那就是20個請求。并且1kb 并不會比 2k 省太多,性價比不是特別高,所以可能 選16384會更為通用一點

責任編輯:武曉燕 來源: 撿田螺的小男孩
相關推薦

2024-08-30 08:59:15

2024-01-17 19:05:44

mget優化數據庫

2022-03-19 12:16:49

Redis高并發系統集群部署

2022-09-05 14:36:26

服務端TCP連接

2011-01-18 18:09:21

GmailThunderbird

2021-06-22 15:06:13

Redis客戶端 Redis-clie

2021-01-26 01:55:24

HTTPS網絡協議加密

2021-03-15 11:20:46

HTTPS優化前端

2023-06-10 23:09:40

Redis場景內存

2009-02-04 17:39:14

ibmdwWebSphereDataPower

2023-08-08 15:50:17

2025-03-28 10:47:05

開發注解Java

2025-04-08 09:20:00

Sentinel限流微服務

2022-01-19 09:03:01

工具

2021-09-22 15:46:29

虛擬桌面瘦客戶端胖客戶端

2010-07-13 14:22:47

SQL Server

2021-06-30 17:38:03

Trie 樹字符Java

2021-03-01 11:53:15

面試偽共享CPU

2021-08-01 23:18:21

Redis Golang命令

2024-04-19 08:05:26

鎖升級Java虛擬機
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 午夜精品一区二区三区在线观看 | 日韩视频专区 | av中文字幕在线观看 | 国产高清一区二区三区 | 欧美aaa级| 久久久久久国产精品三区 | 欧美成人免费 | 国产精品一区三区 | 成人影院在线 | 国产精品一区久久久 | 一区二区国产在线观看 | 国产一级一级国产 | 日本一区二区视频 | 久久久久久久综合 | 国产免费又黄又爽又刺激蜜月al | 福利影院在线看 | 国产综合精品一区二区三区 | 亚洲在线免费观看 | 久久久91精品国产一区二区三区 | 成年免费大片黄在线观看一级 | 欧美精品综合 | 91在线视频免费观看 | 亚洲成人99 | 欧美日韩在线一区 | 蜜桃久久 | 久在线 | 国产精品免费观看 | 久久天堂 | 狠狠干影院 | 亚洲一区在线日韩在线深爱 | 国产亚洲欧美日韩精品一区二区三区 | 天天操夜夜爽 | 一区二区影视 | 午夜影院在线播放 | 毛片一区二区三区 | 999精品视频| 亚洲社区在线 | 777毛片| 在线播放日韩 | 国产精品久久久久9999鸭 | 亚洲一区免费视频 |