redis分片
分片場景
在業務量相對較小的時候,可以將所有數據都存到一台機器上,只使用redis單機模式,不存在分片問題。如果業務的數據量超過一台物理機器的內存大小時,則會面對擴展問題,需要多台機器去存數據,此時,需要使用到redis的分片技術。
如何分片
redis通過分slot的方式進行分片。例如有A、B、C三台機器組成的一個集群。對於集群里面的節點而言,三者會全部覆蓋16384個slots(2K字節bit)。對於每一個請求而言,會通過一個hash算法,得到一個2K字節(16384個slots)范圍內的一個值,這個值則對應唯一一個節點,這個節點處理該請求。
擴容場景
當資源不夠,需要增加節點時,需要對slots進行節點的重復分配。而此時,又不能停止對外服務,解決方案如何?
假設原來有三個節點:A(0至5000),B(5001至10000),C(10001到16383)。現在需要增加第四個節點D節點進來,重新分配如下:
需要將C節點的slots,從13000~16383的slot遷移到D節點中。redis通過提供一組命令原語完成遷移操作。
遷移邏輯
遷移工作,可以使用redis-trib管理軟件進行遷移,具體原理如下:
1、對目標節點,即是D節點發送cluster setslot import 命令,讓目標節點做好准備接收遷移准備。
2、對源節點,即是C節點,發送cluster setslot migrating命令,讓源節點做好准備遷移准備。
3、對源節點,發送cluster getkeysinslot <slot> <count>命令,獲取對應slot的最多count個屬於slot的key名。
4、對於步驟3中獲取的key,向源節點發送命令migrate <target ip> <target port> <key_name> 0 <timeout> 命令,將被選中的鍵原子地從源節點遷移到目標節點。
5、重復上述3,4步驟,直到所有key都遷移成功
遷移期間訪問問題
當在遷移過程中,如果被訪問的slot,可能會有部分key存在在源節點,有部分在目標節點中。
1、當客戶端發送請求到源節點的時候,源節點會查看對應的key是否還在本節點,如果存在,則直接執行命令返回給客戶。如果不存在,則會給客戶端返回一個ASK錯誤,指引客戶端往正在導入的目標slot去請求對應的key。客戶端可以通過返回的ASK錯誤中的目標節點進行對應KEY的請求。
2、當客戶端發送請求到目標節點時。
1)如果客戶端請求時,帶上ASKING標識,由目標節點會執行對應KEY的查詢。正常情況下,如果是通過查詢源slot,獲取ASK錯誤之后,再到目標節點進行查詢的時候,需要帶上ASKING標識。
2)如果客戶端請求時,未帶上ASKING標識,原由上,對應的slot還屬於源節點,則目標節點會拒絕執行KEY查詢,會返回一個MOVED錯誤給客戶端,告訴客戶端對應的KEY的slot屬於源節點。正常情況下,如果第一次請求KEY到了正在遷移的目標節點,則會收到MOVED錯誤。