Redis架構演變與redis-cluster羣集讀寫方案

導言

redis-cluster是近年來redis架構不斷改進中的相對較好的redis高可用方案。本文涉及到近年來redis多實例架構的演變過程,包括普通主從架構(Master、slave可進行寫讀分離)、哨兵模式下的主從架構、redis-cluster高可用架構(redis官方默認cluster下不進行讀寫分離)的簡介。同時還介紹使用Java的兩大redis客戶端:Jedis與Lettuce用於讀寫redis-cluster的數據的通常方法。再經過官方文檔以及互聯網的相關技術文檔,給出redis-cluster架構下的讀寫能力的優化方案,包括官方的推薦的擴展redis-cluster下的Master數量以及非官方默認的redis-cluster的讀寫分離方案,案例中使用Lettuce的特定方法進行redis-cluster架構下的數據讀寫分離。java

近年來redis多實例用架構的演變過程

redis是基於內存的高性能key-value數據庫,若要讓redis的數據更穩定安全,須要引入多實例以及相關的高可用架構。而近年來redis的高可用架構亦不斷改進,前後出現了本地持久化、主從備份、哨兵模式、redis-cluster羣集高可用架構等等方案。node

一、redis普通主從模式

經過持久化功能,Redis保證了即便在服務器重啓的狀況下也不會損失(或少許損失)數據,由於持久化會把內存中數據保存到硬盤上,重啓會從硬盤上加載數據。 。可是因爲數據是存儲在一臺服務器上的,若是這臺服務器出現硬盤故障等問題,也會致使數據丟失。爲了不單點故障,一般的作法是將數據庫複製多個副本以部署在不一樣的服務器上,這樣即便有一臺服務器出現故障,其餘服務器依然能夠繼續提供服務。爲此, Redis 提供了複製(replication)功能,能夠實現當一臺數據庫中的數據更新後,自動將更新的數據同步到其餘數據庫上。redis

在複製的概念中,數據庫分爲兩類,一類是主數據庫(master),另外一類是從數據庫(slave)。主數據庫能夠進行讀寫操做,當寫操做致使數據變化時會自動將數據同步給從數據庫。而從數據庫通常是隻讀的,並接受主數據庫同步過來的數據。一個主數據庫能夠擁有多個從數據庫,而一個從數據庫只能擁有一個主數據庫。
算法

 

主從模式的配置,通常只須要再做爲slave的redis節點的conf文件上加入「slaveof masterip masterport」, 或者做爲slave的redis節點啓動時使用以下參考命令:數據庫

redis-server --port 6380 --slaveof masterIp masterPort   

redis的普通主從模式,能較好地避免單獨故障問題,以及提出了讀寫分離,下降了Master節點的壓力。互聯網上大多數的對redis讀寫分離的教程,都是基於這一模式或架構下進行的。但實際上這一架構並不是是目前最好的redis高可用架構。緩存

 主從複製過程見下圖安全

 

  1. 當一個從數據庫啓動時,會向主數據庫發送sync命令,
  2. 主數據庫接收到sync命令後會開始在後臺保存快照(執行rdb操做),並將保存期間接收到的命令緩存起來
  3. 當快照完成後,redis會將快照文件和全部緩存的命令發送給從數據庫。
  4. 從數據庫收到後,會載入快照文件並執行收到的緩存的命令。

 

二、哨兵(Sentinel)模式高可用架構

 

Redis-Sentinel是Redis官方推薦的高可用性(HA)解決方案。實際上這意味着你可使用Sentinel模式建立一個能夠不用人爲干預而應對各類故障的Redis部署。
 
Redis提供的sentinel(哨兵)機制,經過sentinel模式啓動redis後,自動監控master/slave的運行狀態,基本原理是:心跳機制+投票裁決
  • 監控(Monitoring): Sentinel 會不斷地檢查你的主服務器和從服務器是否運做正常。
  • 提醒(Notification): 當被監控的某個 Redis 服務器出現問題時, Sentinel 能夠經過 API 向管理員或者其餘應用程序發送通知。
  • 自動故障遷移(Automatic failover): 當一個主服務器不能正常工做時, Sentinel 會開始一次自動故障遷移操做, 它會將失效主服務器的其中一個從服務器升級爲新的主服務器, 並讓失效主服務器的其餘從服務器改成複製新的主服務器; 當客戶端試圖鏈接失效的主服務器時, 集羣也會向客戶端返回新主服務器的地址, 使得集羣可使用新主服務器代替失效服務器。

Redis Sentinel 是一個分佈式系統, 你能夠在一個架構中運行多個 Sentinel 進程(progress), 這些進程使用流言協議(gossip protocols)來接收關於主服務器是否下線的信息, 並使用投票協議(agreement protocols)來決定是否執行自動故障遷移, 以及選擇哪一個從服務器做爲新的主服務器。服務器

能夠用info replication查看主從狀況 例子: 1主2從 1哨兵,能夠用命令起也能夠用配置文件裏 可使用雙哨兵,更安全,參考命令以下:架構

redis-server --port 6379 
redis-server --port 6380 --slaveof 192.168.0.167 6379 
redis-server --port 6381 --slaveof 192.168.0.167 6379
redis-sentinel sentinel.conf 

  

其中,哨兵配置文件sentinel.conf參考以下:app

sentinel monitor mymaster 192.168.0.167 6379 1  

  

其中mymaster表示要監控的主數據庫的名字。配置哨兵監控一個系統時,只須要配置其監控主數據庫便可,哨兵會自動發現全部複製該主數據庫的從數據庫。
Master與slave的切換過程:

  1. slave leader升級爲master
  2. 其餘slave修改成新master的slave
  3. 客戶端修改鏈接
  4. 老的master若是重啓成功,變爲新master的slave

這裏寫圖片描述 
這裏寫圖片描述 
這裏寫圖片描述 
這裏寫圖片描述 

三、redis-cluster羣集高可用架構

即便使用哨兵,redis每一個實例也是全量存儲,每一個redis存儲的內容都是完整的數據,浪費內存且有木桶效應。爲了最大化利用內存,能夠採用cluster羣集,就是分佈式存儲。即每臺redis存儲不一樣的內容。
採用redis-cluster架構正是知足這種分佈式存儲要求的集羣的一種體現。redis-cluster架構中,被設計成共有16384個hash slot。每一個master分得一部分slot,其算法爲:hash_slot = crc16(key) mod 16384 ,這就找到對應slot。採用hash slot的算法,其實是解決了redis-cluster架構下,有多個master節點的時候,數據如何分佈到這些節點上去。key是可用key,若是有{}則取{}內的做爲可用key,不然整個能夠是可用key。羣集至少須要3主3從,且每一個實例使用不一樣的配置文件。

 

 

在redis-cluster架構中,redis-master節點通常用於接收讀寫,而redis-slave節點則通常只用於備份,其與對應的master擁有相同的slot集合,若某個redis-master意外失效,則再將其對應的slave進行升級爲臨時redis-master。
在redis的官方文檔中,對redis-cluster架構上,有這樣的說明:在cluster架構下,默認的,通常redis-master用於接收讀寫,而redis-slave則用於備份,當有請求是在向slave發起時,會直接重定向到對應key所在的master來處理。但若是不介意讀取的是redis-cluster中有可能過時的數據而且對寫請求不感興趣時,則亦可經過readonly命令,將slave設置成可讀,而後經過slave獲取相關的key,達到讀寫分離。

具體能夠參閱redis官方文檔(https://redis.io/commands/readonly)等相關內容:

Enables read queries for a connection to a Redis Cluster slave node. Normally slave nodes will redirect clients to the authoritative master for the hash slot involved in a given command, however clients can use slaves in order to scale reads using the READONLY command. READONLY tells a Redis Cluster slave node that the client is willing to read possibly stale data and is not interested in running write queries. When the connection is in readonly mode, the cluster will send a redirection to the client only if the operation involves keys not served by the slave's master node. This may happen because: The client sent a command about hash slots never served by the master of this slave. The cluster was reconfigured (for example resharded) and the slave is no longer able to serve commands for a given hash slot.

 

例如,咱們假設已經創建了一個三主三從的redis-cluster架構,其中A、B、C節點都是redis-master節點,A一、B一、C1節點都是對應的redis-slave節點。在咱們只有master節點A,B,C的狀況下,對應redis-cluster若是節點B失敗,則羣集沒法繼續,由於咱們沒有辦法再在節點B的所具備的約三分之一的hash slot集合範圍內提供相對應的slot。然而,若是咱們爲每一個主服務器節點添加一個從服務器節點,以便最終集羣由做爲主服務器節點的A,B,C以及做爲從服務器節點的A1,B1,C1組成,那麼若是節點B發生故障,系統可以繼續運行。節點B1複製B,而且B失效時,則redis-cluster將促使B的從節點B1做爲新的主服務器節點而且將繼續正確地操做。但請注意,若是節點B和B1在同一時間發生故障,則Redis羣集沒法繼續運行。

Redis羣集配置參數:在繼續以前,讓咱們介紹一下Redis Cluster在redis.conf文件中引入的配置參數。有些命令的意思是顯而易見的,有些命令在你閱讀下面的解釋後纔會更加清晰。

  1. cluster-enabled :若是想在特定的Redis實例中啓用Redis羣集支持就設置爲yes。 不然,實例一般做爲獨立實例啓動。
  2. cluster-config-file :請注意,儘管有此選項的名稱,但這不是用戶可編輯的配置文件,而是Redis羣集節點每次發生更改時自動保留羣集配置(基本上爲狀態)的文件。
  3. cluster-node-timeout :Redis羣集節點能夠不可用的最長時間,而不會將其視爲失敗。 若是主節點超過指定的時間不可達,它將由其從屬設備進行故障切換。
  4. cluster-slave-validity-factor :若是設置爲0,不管主設備和從設備之間的鏈路保持斷開鏈接的時間長短,從設備都將嘗試故障切換主設備。 若是該值爲正值,則計算最大斷開時間做爲節點超時值乘以此選項提供的係數,若是該節點是從節點,則在主鏈路斷開鏈接的時間超過指定的超時值時,它不會嘗試啓動故障切換。
  5. cluster-migration-barrier :主設備將保持鏈接的最小從設備數量,以便另外一個從設備遷移到不受任何從設備覆蓋的主設備。有關更多信息,請參閱本教程中有關副本遷移的相應部分。
  6. cluster-require-full-coverage :若是將其設置爲yes,則默認狀況下,若是key的空間的某個百分比未被任何節點覆蓋,則集羣中止接受寫入。 若是該選項設置爲no,則即便只處理關於keys子集的請求,羣集仍將提供查詢。

如下是最小的Redis集羣配置文件:

port 7000
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes

  

注意:

  1. redis-cluster最小配置爲三主三從,當1個主故障,你們會給對應的從投票,把從立爲主,若沒有從數據庫能夠恢復則redis羣集就down了。
  2. 在這個redis cluster中,若是你要在slave讀取數據,那麼須要帶上readonly指令。redis cluster的核心的理念,主要是用slave作高可用的,每一個master掛一兩個slave,主要是作數據的熱備,當master故障時的做爲主備切換,實現高可用的。redis cluster默認是不支持slave節點讀或者寫的,跟咱們手動基於replication搭建的主從架構不同的。slave node要設置readonly,而後再get,這個時候才能在slave node進行讀取。對於redis -cluster主從架構,若要進行讀寫分離,官方實際上是不建議的,但也能作,只是會複雜一些。具體見下面的章節。
  3. redis-cluster的架構下,實際上自己master就是能夠任意擴展的,你若是要支撐更大的讀吞吐量,或者寫吞吐量,或者數據量,均可以直接對master進行橫向擴展就能夠了。也擴容master,跟以前擴容slave進行讀寫分離,效果是同樣的或者說更好。
  4. 可使用自帶客戶端鏈接:使用redis-cli -c -p cluster中任意一個端口,進行數據獲取測試。
相關文章
相關標籤/搜索