天天看點

《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用戶端全量清單,以确定是否有适合于你的程式設計語言、成熟的一緻性哈希實作的用戶端。