閱讀288 返回首頁    go 阿裏雲 go 技術社區[雲棲]


《Redis官方文檔》分區

分區:如何把數據存儲到多個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-rbPredis

請檢查Redis客戶端全量列表,以確定是否有適合於你的編程語言、成熟的一致性哈希實現的客戶端。

最後更新:2017-05-22 09:31:57

  上一篇:go  《Redis官方教程》-基準測試
  下一篇:go  Nodejs進階:Express常用中間件body-parser實現解析