Redis分片機制

逆月翎發表於2019-10-11

文章原創於公眾號:程式猿周先森。本平臺不定時更新,喜歡我的文章,歡迎關注我的微信公眾號。

file

前兩篇文章對Redis主從複製和主從切換的知識點進行了介紹,但是也很明顯的有一點小弊端:

  • 需要定時進行主從複製會影響Redis效能。
  • 主節點當機後,從所有從節點選擇進行主從切換。主從切換的過程中非服務不可用。

引入分片概念--分片機制的作用

而本篇文章主要談談Redis的分片機制,如果沒有分片機制,Redis就被侷限於單機所支援的記憶體容量。Redis的分片機制允許資料拆分存放在不同的Redis例項上,每個Redis例項只包含所有鍵的子集。可以減輕單臺Redis的壓力,提升Redis擴充套件能力和計算能力。如果我們只使用一個Redis例項,當Redis當機將會直接停止服務,所以我們可以採取分片機制,將原本一臺Redis例項維護的資料,改為由多個Redis例項共同維護這部分資料。

分片方案(1)範圍分片

分片需要將不同key對映到不同Redis例項上儲存,所以key的對映規則需要制定一個演算法,最簡單的一個分片方案應該是範圍分片。範圍分片理解起來很簡單,比如我們儲存使用者基本資訊,我們制定一個演算法將使用者userid從0到1000對映到例項A,userid從1000到2000對映到例項B,以此類推。這個方案很輕鬆可以使用,但是引發了一個問題:我們需要維護user_id範圍和對映例項之間的關係。而正是這個問題導致範圍分片雖然簡單,但是效率比其他分片方案低效許多,所以Redis中一般不會使用範圍分片作為分片方案。

(2)雜湊分片

比如我們目前有四個Redis例項,我們需要儲存一個key。我們可以通過雜湊函式crc32()將key名轉換成一個長整型數字,然後對長整型數字對4取餘,就可以得到對映的例項。但是這種分配方案一樣存在弊端:當我們需要增加或移除Redis例項時,就會造成大量key無法被命中。所以這時候出現了一種雜湊分片的高階形式--一致性雜湊。一致性雜湊有三大特性:

  • key雜湊結果儘可能分配到不同Redis例項。
  • 當例項增加或移除,需要保護已對映的內容不會重新被分配到新例項上。
  • 對key的雜湊應儘量避免重複。

但是在Redis中沒有使用一致性雜湊這個概念,而是引入了雜湊槽。在Redis叢集中共有16384個雜湊槽,然後每個key通過雜湊函式crc16()將key名轉化成一個長整型數字再對16384取餘,最終決定這個key儲存的雜湊槽。而每個Redis例項負責維護一部分雜湊槽,所有例項共同維護所有的雜湊槽。使用雜湊槽最顯而易見的特點就是Redis例項的增加或者移除很方便,而不需要暫停所有Redis例項服務。

分片實現

上一篇談到主從切換的哨兵模式已經提到,哨兵模式可以實現高可用以及讀寫分離,但是缺點在於所有Redis例項儲存的資料全部一致,所以Redis支援cluster模式,可以簡單將cluster理解為Redis叢集管理的一個外掛,通過它可以實現Redis的分散式儲存。

資料分片方式一般有三種:客戶端分片、代理分片和伺服器分片。

客戶端分片

定義:客戶端自己計算key需要對映到哪一個Redis例項。

優點:客戶端分片最明顯的好處在於降低了叢集的複雜度,而伺服器之間沒有任何關聯性,資料分片由客戶端來負責實現。

缺點:客戶端實現分片則客戶端需要知道當前叢集下不同Redis例項的資訊,當新增Redis例項時需要支援動態分片,多數Redis需要重啟才能實現該功能。

代理分片

定義:客戶端將請求傳送到代理,代理通過計算得到需要對映的叢集例項資訊,然後將客戶端的請求轉發到對應的叢集例項上,然後返回響應給客戶端。

優點:降低了客戶端的複雜度,客戶端不用關心後端Redis例項的狀態資訊。

缺點:多了一箇中間分發環節,所以對效能有些取的損失。

伺服器分片

定義:客戶端可以和叢集中任意Redis例項通訊,當客戶端訪問某個例項時,伺服器進行計算key應該對映到哪個具體的Redis例項中儲存,如果對映的例項不是當前例項,則該例項主動引導客戶端去對應例項對key進行操作。這其實是一個重定向的過程。這個過程不是從當前Redis例項轉發到對應的Redis例項,而是客戶端收到伺服器通知具體對映的Redis例項重定向到對映的例項中。當前還不能完全適用於生產環境。

優點:支援高可用,任意例項都有主從,主掛了從會自動接管。

缺點:需要客戶端語言實現伺服器叢集協議,但是目前大多數語言都有其客戶端實現版本。

預分片

從上面可以清楚地看出,分片機制增加或移除例項是非常麻煩的一件事,所以我們可以考慮一開始就開啟32個節點例項,當我們可以新增Redis伺服器時,我們可以將一半的節點移動到新的Redis伺服器。這樣我們只需要在新伺服器啟動一個空節點,然後移動資料,配置新節點為源節點的從節點,然後更新被移動節點的ip資訊,然後向新伺服器傳送slaveof命令關閉主從配置,最後關閉舊伺服器不需要使用的例項並且重新啟動客戶端。這樣我們就可以在幾乎不需要停機時間時完成資料的移動。

分片機制的缺點

  • 分片是由多臺Redis例項共同運轉,所以如果其中一個Redis例項當機,則整個分片都將無法使用,所以分片機制無法實現高可用。
  • 如果有不同的key對映到不同的Redis例項,這時候不能對這兩個key做交集或者使用事務。
  • 使用分片機制因為涉及多例項,資料處理比較複雜。
  • 分片中對於例項的新增或刪除會很複雜,不過可以使用預分片技術進行改善。

歡迎關注公眾號:程式猿周先森。file

本文由部落格一文多發平臺 OpenWrite 釋出!

相關文章