Redis集羣方案應該怎麼作

方案1:Redis官方集羣方案 Redis Cluster

Redis Cluster是一種服務器sharding分片技術。Redis Cluster集羣如何搭建請參考個人另外一篇博文:http://www.cnblogs.com/xckk/p/6144447.html html

Redis3.0版本開始正式提供,解決了多Redis實例協同服務問題,時間較晚,目前能證實在大規模生產環境下成功的案例還不是不少,須要時間檢驗。java

Redis Cluster中,Sharding採用slot(槽)的概念,一共分紅16384個槽。對於每一個進入Redis的鍵值對,根據key進行散列,分配到這16384個slot中的某一箇中。使用的hash算法也比較簡單,CRC16後16384取模。node

Redis Cluster中的每一個node負責分攤這16384個slot中的一部分,也就是說,每一個slot都對應一個node負責處理。例如三臺node組成的cluster,分配的slot分別是0-5460,5461-10922,10923-16383,redis

M: 434e5ee5cf198626e32d71a4aee27bc4058b4e45 127.0.0.1:7000

slots:0-5460 (5461 slots) master
M: 048a0c9631c87e5ecc97a4ce5834d935f2f938b6 127.0.0.1:7001

slots:5461-10922 (5462 slots) master

M: 04ae4184b2853afb8122d15b5b2efa471d4ca251 127.0.0.1:7002

slots:10923-16383 (5461 slots) master

 

添加或減小節點時?算法

當動態添加或減小node節點時,須要將16384個slot從新分配,所以槽中的鍵值也要遷移。這一過程,目前處於半自動狀態,須要人工介入。數據庫

 

節點發生故障時後端

若是某個node發生故障,那它負責的slots也就失效,整個Redis Cluster將不能工做。所以官方推薦的方案是將node都配置成主從結構,即一個master主節點,掛n個slave從節點。centos

這很是相似Redis Sharding場景下服務器節點經過Sentinel(哨兵)監控架構主從結構,只是Redis Cluster自己提供了故障轉移容錯的能力。緩存

 

通訊端口服務器

Redis Cluster的新節點識別能力、故障判斷及故障轉移能力是經過集羣中的每一個node和其它的nodes進行通訊,這被稱爲集羣總線(cluster bus)。

通訊端口號通常是該node端口號加10000。如某node節點端口號是6379,那麼它開放的通訊端口是16379。nodes之間的通訊採用特殊的二進制協議。

 

對客戶端來講,整個cluster被看重是一個總體,客戶端能夠鏈接任意一個node進行操做,就像操做單一Redis實例同樣,當客戶端操做的key沒有分配到該node上時,Redis會返回轉向指令,指向正確的node。

以下。在127.0.0.1上部署了三臺Redis實例,組成Redis cluster,端口號分別是7000,7001,7002。在端口號爲7000的Redis node上設置<foo,hello>,foo對應的key值重定向到端口號爲7002的node節點上。get foo命令時,也會重定向到7002上的node節點上去取數據,返回給客戶端。

[root@centos1 create-cluster]# redis-cli -c -p 7000

127.0.0.1:7000> set foo hello

-> Redirected to slot [12182] located at 127.0.0.1:7002

OK

127.0.0.1:7000> get foo

-> Redirected to slot [12182] located at 127.0.0.1:7002

"hello"

 

方案2:Redis Sharding集羣

Redis Sharding是一種客戶端Sharding分片技術。

Redis Sharding能夠說是Redis Cluster出來以前,業界廣泛使用的多Redis實例集羣方法。主要思想是採用哈希算法將Redis數據的key進行散列,經過hash函數,特定的key會映射到特定的Redis節點上。

這樣,客戶端就知道該向哪一個Redis節點操做數據,須要說明的是,這是在客戶端完成的。Sharding架構如圖所示:

clipboard

 

java redis客戶端jedis,已支持Redis Sharding功能,即ShardedJedis以及結合緩存池的ShardedJedisPool。Jedis的Redis Sharding實現具備以下特色:

一、採用一致性哈希算法(consistent hashing)

將key和節點name同時哈希,而後進行映射匹配,採用的算法是MURMUR_HASH。一致性哈希主要緣由是當增長或減小節點時,不會產生因爲從新匹配形成的rehashing。一致性哈希隻影響相鄰節點key分配,影響量小。更多一致性哈希算法介紹,能夠參考:http://blog.csdn.net/cywosp/article/details/23397179/

二、虛擬節點

ShardedJedis會對每一個Redis節點,根據名字虛擬化出160個虛擬節點進行散列。用虛擬節點作映射匹配,能夠在增長或減小Redis節點時,key在各Redis節點移動更分配更均勻,而不是隻有相鄰節點受影響。如圖,Redis節點1虛擬化成NODE1-1和NODE1-2,散列中哈希環上。這樣當object一、object2散列時,選取最近節點NODE1-1和NODE1-2,而NODE1-1和NODE1-2又是NODE節點的虛擬節點,即實際存儲在NODE節點上。

增長虛擬節點,能夠保證平衡性,即每臺Redis機器,存儲的數據都差很少,而不是一臺機器存儲的數據較多,其它的少。

clipboard[1]

三、ShardedJedis支持keyTagPattern模式

抽取key的一部分keyTag作sharding,這樣經過合理命名key,能夠將一組相關聯的key放入同一Redis節點,避免跨節點訪問。即客戶端將相同規則的key值,指定存儲在同一Redis節點上。

 

添加或減小節點時?

Redis Sharding採用客戶端Sharding方式,服務端的Redis仍是一個個相對獨立的Redis實例節點。同時,咱們也不須要增長額外的中間處理組件,這是一種很是輕量、靈活的Redis多實例集羣方案。

固然,這種輕量靈活方式必然在集羣其它能力方面作出妥協。好比擴容,當想要增長Redis節點時,儘管採用一致性哈希,那麼不一樣的key分佈到不一樣的Redis節點上。

當咱們須要擴容時,增長機器到分片列表中。這時候客戶端根據key算出來落到跟原來不一樣的機器上,這樣若是要取某一個值,會出現取不到的狀況。

對於這一種狀況,通常的做法是取不到後,直接從後端數據庫從新加載數據,但有些時候,擊穿緩存層,直接訪問數據庫層,會對系統訪問形成很大壓力。

 

Redis做者給出了一個辦法--presharding。

是一種在線擴容的方法,原理是將每一臺物理機上,運行多個不一樣端口的Redis實例,假如三個物理機,每一個物理機運行三個Redis實例,那麼咱們的分片列表中實際有9個Redis實例,當咱們須要擴容時,增長一臺物理機,步驟以下:

一、在新的物理機上運行Redis-server

二、該Redis-server從屬於(slaveof)分片列表中的某一Redis-Server(假設叫RedisA)。

三、主從複製(Replication)完成後,將客戶端分片列表中RedisA的IP和端口改成新物理機上Redis-Server的IP和端口。

四、中止RedisA

這樣至關於將某一Redis-Server轉移到了一臺新機器上。但仍是很依賴Redis自己的複製功能,若是主庫快照數據文件過大,這個複製的過程也會好久,同時也會給主Redis帶來壓力,因此作這個拆分的過程最好選擇業務訪問低峯時段進行。

 

節點發生故障時

並非只有增刪Redis節點引發鍵值丟失問題,更大的障礙來自Redis節點忽然宕機。

爲不影響Redis性能,儘可能不開啓AOF和RDB文件保存功能,所以需架構Redis主備模式,主Redis宕機,備Redis留有備份,數據不會丟失。

Sharding演變成以下:

clipboard[2]

這樣,咱們的架構模式變成一個Redis節點切片包含一個主Redis和一個備Redis,主備共同組成一個Redis節點,經過自動故障轉移,保證了節點的高可用性.

 

Redis Sentinel哨兵

提供了主備模式下Redis監控、故障轉移等功能,達到系統的高可用性。

 

讀寫分離

高訪問時量下,即便採用Sharding分片,一個單獨節點仍是承擔了很大的訪問壓力,這時咱們還須要進一步分解。

一般狀況下,讀經常是寫的數倍,這時咱們能夠將讀寫分離,讀提供更多的實例數。利用主從模式實現讀寫分離,主負責寫,從負責只讀,同時一主掛多個從。在Redis Sentinel監控下,還能夠保障節點故障的自動監測。

 

方案3:利用代理中間件實現大規模Redis集羣

上面分別介紹了基於客戶端Sharding的Redis Sharding和基於服務端sharding的Redis Cluster。

客戶端Sharding技術

優點:服務端的Redis實例彼此獨立,相互無關聯,很是容易線性擴展,系統靈活性很強。

不足:一、因爲sharding處理放到客戶端,規模擴大時給運維帶來挑戰。

二、服務端Redis實例羣拓撲結構有變化時,每一個客戶端都須要更新調整。

三、鏈接不能共享,當應用規模增大時,資源浪費制約優化。

服務端Sharding技術

優點:服務端Redis集羣拓撲結構變化時,客戶端不須要感知,客戶端像使用單Redis服務器同樣使用Redis Cluster,運維管理也比較方便。

不足:Redis Cluster正式版推出時間不長,系統穩定性、性能等須要時間檢驗,尤爲中大規模使用場景。

 

能不能結合兩者優點?既能使服務端各實例彼此獨立,支持線性可伸縮,同時sharding又能集中處理,方便統一管理?

 

中間件sharding分片技術

twemproxy就是一種中間件sharding分片的技術,處於客戶端和服務器的中間,將客戶端發來的請求,進行必定的處理後(如sharding),再轉發給後端真正的Redis服務器。

也就是說,客戶端不直接訪問Redis服務器,而是經過twemproxy代理中間件間接訪問。

 

tweproxy中間件的內部處理是無狀態的,起源於twitter,不只支持redis,同時支持memcached。

使用了中間件,twemproxy能夠經過共享與後端系統的鏈接,下降客戶端直接鏈接後端服務器的鏈接數量。同時,它也提供sharding功能,支持後端服務器集羣水平擴展。統一運維管理也帶來了方便。

固然,因爲使用了中間件,相比客戶端直轄服務器方式,性能上確定會有損耗,大約下降20%左右。

另外一個知名度較高的實現是 Codis,由豌豆莢的團隊開發。感興趣的讀者能夠搜索相關資料。

 

總結:幾種方案如何選擇。

上面大體講了三種集羣方案,主要根據sharding在哪一個環節進行區分

一、服務端實現分片

官方的 Redis Cluster 實現就是採用這種方式,在這種方案下,客戶端請求到達錯誤節點後不會被錯誤節點代理執行,而是被錯誤節點重定向至正確的節點。

二、客戶端實現分片

分區的邏輯在客戶端實現,由客戶端本身選擇請求到哪一個節點。方案可參考一致性哈希,基於 Memcached 的 cache 集羣通常是這麼作,而這種方案一般適用於用戶對客戶端的行爲有徹底控制能力的場景。

三、中間件實現分片

有名的例子是 Twitter 的 Twemproxy,Redis 做者對其評價較高。一篇較舊的博客以下:Twemproxy, a Redis proxy from Twitter

另外一個知名度較高的實現是 Codis,由豌豆莢的團隊開發,做者 @go routine 劉老師已經在前面的答案中推薦過了。

 

那麼,如何選擇呢?

顯然在客戶端作分片是自定義能力最高的。

優點在於,在不須要客戶端服務端協做,以及沒有中間層的條件下,每一個請求的 roundtrip 時間是相對更小的,搭配良好的客戶端分片策略,可讓整個集羣得到很好的擴展性。

固然劣勢也很明顯,用戶須要本身對付 Redis 節點宕機的狀況,須要採用更復雜的策略來作 replica,以及須要保證每一個客戶端看到的集羣「視圖」是一致的。

 

中間件的方案對客戶端實現的要求是最低的,客戶端只要支持基本的 Redis 通訊協議便可,至於擴容、多副本、主從切換等機制客戶端都沒必要操心,所以這種方案也很適合用來作「緩存服務」。

 

官方推出的協做方案也完整地支持了分片和多副本,相對於各類 proxy,這種方案假設了客戶端實現是能夠與服務端「協做」的,事實上主流語言的 SDK 都已經支持了。

因此,對於大部分使用場景來講,官方方案和代理方案都夠用了,其實不必太糾結誰更勝一籌,每種方案都有不少靠譜的公司在用。

 

此文主要參考瞭如下文章:

https://www.zhihu.com/question/21419897

http://blog.csdn.net/freebird_lb/article/details/7778999

 

秀才坤坤出品

轉載請註明來源http://www.cnblogs.com/xckk/p/6134655.html 

相關文章
相關標籤/搜索