《Redis官方文件》分割槽
原文連結 譯者:Alexandar Mahone
分割槽:如何把資料儲存到多個Redis例項中
分割槽就是把你的資料分割到多個Redis例項中的一個過程,因此每個例項僅僅包含部分鍵。這篇文章第一部分介紹分割槽概念,第二部分將介紹Redis分割槽的用法。
(譯者注:Redis叢集是分割槽事實上標準)
為什麼分割槽是非常有用的
分割槽在Redis中主要有兩個目的:
- 分割槽利用多臺機器的記憶體構建一個更大資料庫。如果不使用分割槽,資料庫大小受限於單個計算機記憶體。
- 分割槽可以在多核和多計算機之間彈性擴充套件計算能力,並且分割槽可以在多計算機和網路介面卡之間彈性擴充套件網路頻寬。
分割槽基礎:
有多種的分割槽標準。假設我們有4個Redis例項 R0,R1,R2,R3,很多表示使用者的鍵例如 user:1,user:2等等,我們可以找到不同方式選擇例項儲存指定的鍵。換句話說有不同的系統對映一個指定的鍵到一個給定的Redis伺服器。
一個最簡單的方法是使用範圍分割槽,並且通過對映某一範圍的物件到特定的Redis例項。例如,我可以指定ID 0到10000的使用者儲存到例項R0,而ID 10001到20000的使用者儲存到例項R2等等。
該方案實際上是可以應用在實踐中的,儘管他的缺點是需要一張對映物件範圍與例項的表。這張表需要進行維護,並且我們需要為每種型別物件建立一張表,所以範圍分割槽在Redis中常常是不受歡迎的,因為比其他分割槽方法更低效。
- 一個範圍分割槽替代方法是雜湊分割槽。此方案適用於任何形式鍵,無需鍵格式形如object_name:<id>,就是這麼簡單:
使用雜湊方法(例如crc32雜湊方法)將鍵名轉換成數字。例如一個鍵名是foobar,crc32(foobar)輸出結果形如93024922。 - 我是使用取模操作將該數字轉換成0到3的數字,以便對映到四個Redis例項中的一個。93024922對4取餘數等於2,這樣我知道foobar鍵應該儲存到R2例項中。注意:模操作返回除法運算的餘數,大部分程式語言使用%(取餘)就可以了。
通過這兩個例子,你應該可以想到還有很多其他方法進行分割槽。一個更先進的雜湊分割槽是一致性雜湊,並且是由幾個Redis客戶端和代理實現的。
分割槽不同實現方式
分割槽可以由一個軟體棧的不同部分完成。
- 客戶端分割槽:客戶端直接選擇正確節點讀寫指定鍵。很多Redis客戶實現了這種分割槽方式。
- 代理輔助分割槽:是指我們的客戶端通過Redis協議把請求傳送給代理,而不是直接傳送給真正的Redis例項伺服器。這個代理會確保我們的請求根據配置分割槽策略傳送到正確的Redis例項上,並返回給客戶端。Redis和Memcached的代理都是用Twemproxy (譯者注:這是twitter開源的一個代理框架)來實現代理服務分割槽的。
- 查詢路由:是指你可以把一個請求傳送給一個隨機的例項,這時例項會把該查詢轉發給正確的節點。通過客戶端重定向(客戶端的請求不用直接從一個例項轉發到另一個例項,而是被重定向到正確的節點),Redis叢集實現了一種混合查詢路由。
Redis分割槽缺點:
Redis分割槽在有些方面做的並不好:
- 不支援多個鍵的操作。比如你不能操作對映在兩個Redis例項上的兩個集合的交叉集。(其實可以做到這一點,但是需要間接的解決).
- Redis不支援多個鍵的事務。
- Redis是以鍵來分割槽,因此不能使用單個大鍵對資料集進行分片,例如一個非常大的有序集。
- 如果使用分割槽,資料的處理會變得複雜,比如你必須處理多個RDB和AOF檔案,在多個例項和主機之間持久化你的資料。
- 新增和刪除節點也會變得複雜。例如通過在執行時新增和刪除節點,Redis叢集通常支援透明地再均衡資料,但是其他系統像客戶端分割槽或者代理分割槽的特性就不支援該特性。不過Pre-sharding(預分片)可以在這方面提供幫助。
作為資料儲存還是作為快取使用?
使用Redis儲存資料或者快取資料在概念上是相同的,但是Redis被當作資料儲存使用時有一個顯著限制。當Redis被當作資料儲存伺服器使用的時候意味著對於相同的鍵值必須被對映到相同的例項上面,但是如果把Redis當作資料快取器,使用多個不同節點,一個給定節點掛掉並不是個大問題,改變鍵值和例項對映表可以提升系統的可用性(也就是系統處理查詢請求的能力)。
如果一個指定鍵的首選節點不可用,一致性雜湊可以為指定鍵切換到其他的節點上。同樣的,你新增一個新的節點,部分新的鍵值開始儲存到新新增的節點上面。
主要的概念如下:
- 如果Redis只作為可伸縮快取伺服器來使用,那麼用一致性雜湊是非常容易的。
- 若果Redis被作為資料持久化伺服器,需要提供節點和鍵值的固定對映,還有節點數目必須是固定的,不能改變。否則當增加或刪除節點時,我們需要一個系統來為鍵重新分配節點,從2015年4月1日開始,Redis叢集提供該特性。
預分片
從分割槽的概念中,我們知道分割槽有一個缺點:除非只把Redis當作快取伺服器來使用,否則新增和刪除Redis節點都會非常複雜。相反使用固定的鍵值和例項對映更加簡單。
然而資料儲存會經常需要變化。今天我只需要10個Redis節點(例項),但是明天我可能會需要50個節點。
因為Redis足夠輕量和小巧(一個備用例項使用1M的記憶體),解決這個問題的簡單方法就是一開始就使用大量的例項節點。即使你開始只有一個伺服器,你可以換成分散式的結構,通過分割槽分方式在單個伺服器上來執行多個Redis例項。
你一開始可以選擇的例項可數可以非常大。例如,32或者64個例項能夠滿足絕大多數的使用者,並且可以為其提供足夠的增長空間。
通過這樣的方法,當摸得資料儲存需求增加時,你只需要更多的Redis伺服器,然後把一個節點移動到另外的伺服器上面。一旦你添加了額外的伺服器,你需要將一半的Redis的例項移動到第二個伺服器,以此類推。
你可以使用Redis 的主從複製來減少服務的停止時間:
- 在新伺服器上開啟新的redis空例項。
- 將節點的資料配置移動到新的從伺服器上
- 停止你的redis客戶端。
- 在新的伺服器上更新IP地址到移動過來的節點配置檔案中。
- 傳送SLAVEOF NO ONE 命令到新伺服器的從節點。
- 使用新的配置重啟客戶端。
- 最後關閉老伺服器上不再使用的節點。
分割槽實踐
到目前為止,我們講了分割槽的原理。但是該如何實戰?你應該使用什麼樣的系統?
Redis叢集
推薦使用Redis叢集獲得自動分片和高可用性。Redis叢集是2015年4月1日版本釋出的可用和生成就緒特性。可以從叢集教程中獲取更多資訊。
一旦Redis叢集是可用的,並且一個Redis叢集相容客戶端支援您的程式語言,Redis叢集就是Redis分割槽事實上標準。
Redis叢集混合使用了查詢路由和客戶端分割槽。
Twemproxy 框架
Twemproxy是一個由Twitter開發的適合Memached ASCII和Redis協議的代理。它是單執行緒工作,使用C語言實現的,速度非常快。並且是基於Apache 2.0 協議的開源軟體。
Twemproxy支援自動在多個redis節點分割槽,如果某個節點不可用,將會被自動遮蔽(這將改變鍵值和節點對映表,所以如果你把Redis當作快取伺服器使用,你應該使用這個功能)。
你可以啟用多個代理,讓你的客戶端得到可用的連線,這樣不會發生單點故障。
Twemproxy基本上是Redis和客戶端的一箇中間層,通過簡化使用讓我們使用可靠的分割槽。
你可以在antirez的部落格獲取有關Twemproxy的更多知識。
客戶端一致性雜湊實現。
替代Twemproxy的一種方案是使用客戶端一致性哈西或者其他類似的演算法。有很多Redis客戶端支援一致性雜湊,比如Redis-rb和Predis。
請檢查Redis客戶端全量列表,以確定是否有適合於你的程式語言、成熟的一致性雜湊實現的客戶端。