當前位置:
首頁 > 科技 > Redis Cluster探索與思考

Redis Cluster探索與思考

作者 | 張冬洪

責編 | 仲培藝

Redis Cluster的基本原理和架構

Redis Cluster是分布式Redis的實現。隨著Redis版本的更替,以及各種已知bug的fixed,在穩定性和高可用性上有了很大的提升和進步,越來越多的企業將Redis Cluster實際應用到線上業務中,通過從社區獲取到反饋社區的迭代,為Redis Cluster成為一個可靠的企業級開源產品,在簡化業務架構和業務邏輯方面都起著積極重要的作用。下面從Redis Cluster的基本原理為起點開啟Redis Cluster在業界的分析與思考之旅。

基本原理

Redis Cluster的基本原理可以從數據分片、數據遷移、集群通訊、故障檢測以及故障轉移等方面進行了解,Cluster相關的代碼也不是很多,注釋也很詳細,可自行查看,地址是:https://github.com/antirez/redis/blob/unstable/src/cluster.c。這裡由於篇幅的原因,主要從數據分片和數據遷移兩方面進行詳細介紹:

數據分片

Redis Cluster在設計中沒有使用一致性哈希(Consistency Hashing),而是使用數據分片(Sharding)引入哈希槽(hash slot)來實現;一個 Redis Cluster包含16384(0~16383)個哈希槽,存儲在Redis Cluster中的所有鍵都會被映射到這些slot中,集群中的每個鍵都屬於這16384個哈希槽中的一個,集群使用公式slot=CRC16(key)/16384來計算key屬於哪個槽,其中CRC16(key)語句用於計算key的CRC16 校驗和。

集群中的每個主節點(Master)都負責處理16384個哈希槽中的一部分,當集群處於穩定狀態時,每個哈希槽都只由一個主節點進行處理,每個主節點可以有一個到N個從節點(Slave),當主節點出現宕機或網路斷線等不可用時,從節點能自動提升為主節點進行處理。

如圖1,ClusterNode數據結構中的slots和numslots屬性記錄了節點負責處理哪些槽。其中,slot屬性是一個二進位位數組(bitarray),其長度為16384/8=2048 Byte,共包含16384個二進位位。集群中的Master節點用bit(0和1)來標識對於某個槽是否擁有。比如,對於編號為1的槽,Master只要判斷序列第二位(索引從0開始)的值是不是1即可,時間複雜度為O(1)。

圖1 ClusterNode數據結構

集群中所有槽的分配信息都保存在ClusterState數據結構的slots數組中,程序要檢查槽i是否已經被分配或者找出處理槽i的節點,只需要訪問clusterState.slots[i]的值即可,複雜度也為O(1)。ClusterState數據結構如圖2所示。

圖2 ClusterState數據結構

查找關係如圖3所示。

圖3 查找關係圖

數據遷移

數據遷移可以理解為slot和key的遷移,這個功能很重要,極大地方便了集群做線性擴展,以及實現平滑的擴容或縮容。那麼它是一個怎樣的實現過程?下面舉個例子:現在要將Master A節點中編號為1、2、3的slot遷移到Master B節點中,在slot遷移的中間狀態下,slot 1、2、3在Master A節點的狀態表現為MIGRATING,在Master B節點的狀態表現為IMPORTING。

MIGRATING狀態

這個狀態如圖4所示是被遷移slot在當前所在Master A節點中出現的一種狀態,預備遷移slot從Mater A到Master B的時候,被遷移slot的狀態首先變為MIGRATING狀態,當客戶端請求的某個key所屬的slot的狀態處於MIGRATING狀態時,會出現以下幾種情況:

圖4 slot遷移的中間狀態

如果key存在則成功處理。

如果key不存在,則返回客戶端ASK,客戶端根據ASK首先發送ASKING命令到目標節點,然後發送請求的命令到目標節點。

當key包含多個命令時:

如果都存在則成功處理

如果都不存在,則返回客戶端ASK

如果一部分存在,則返回客戶端TRYAGAIN,通知客戶端稍後重試,這樣當所有的key都遷移完畢,客戶端重試請求時會得到ASK,然後經過一次重定向就可以獲取這批鍵

此時並不刷新客戶端中node的映射關係

IMPORTING狀態

這個狀態如圖2所示是被遷移slot在目標Master B節點中出現的一種狀態,預備遷移slot從Mater A到Master B的時候,被遷移slot的狀態首先變為IMPORTING狀態。在這種狀態下的slot對客戶端的請求可能會有下面幾種影響:

如果key不存在則新建。

如果key不在該節點上,命令會被MOVED重定向,刷新客戶端中node的映射關係。

如果是ASKING命令則命令會被執行,從而key沒在被遷移的節點,已經被遷移到目標節點的情況命令可以被順利執行。

鍵空間遷移

這是完成數據遷移的重要一步,鍵空間遷移是指當滿足了slot遷移前提的情況下,通過相關命令將slot 1、2、3中的鍵空間從Master A節點轉移到Master B節點,這個過程由MIGRATE命令經過3步真正完成數據轉移。步驟示意如圖5。

圖5 表空間遷移步驟

經過上面三步可以完成鍵空間數據遷移,然後再將處於MIGRATING和IMPORTING狀態的槽變為常態即可,從而完成整個重新分片的過程。

架構

實現細節:

Redis Cluster中節點負責存儲數據,記錄集群狀態,集群節點能自動發現其他節點,檢測出節點的狀態,並在需要時剔除故障節點,提升新的主節點。

Redis Cluster中所有節點通過PING-PONG機制彼此互聯,使用一個二級制協議(Cluster Bus) 進行通信,優化傳輸速度和帶寬。發現新的節點、發送PING包、特定情況下發送集群消息,集群連接能夠發布與訂閱消息。

客戶端和集群中的節點直連,不需要中間的Proxy層。理論上而言,客戶端可以自由地向集群中的所有節點發送請求,但是每次不需要連接集群中的所有節點,只需要連接集群中任何一個可用節點即可。當客戶端發起請求後,接收到重定向(MOVEDASK)錯誤,會自動重定向到其他節點,所以客戶端無需保存集群狀態。不過客戶端可以緩存鍵值和節點之間的映射關係,這樣能明顯提高命令執行的效率。

Redis Cluster中節點之間使用非同步複製,在分區過程中存在窗口,容易導致丟失寫入的數據,集群即使努力嘗試所有寫入,但是以下兩種情況可能丟失數據:

Redis集群的節點不可用後,在經過集群半數以上Master節點與故障節點通信超過cluster-node-timeout時間後,認為該節點故障,從而集群根據自動故障機制,將從節點提升為主節點。這時集群恢復可用。

Redis Cluster的優勢和不足

優勢

1. 無中心架構。

2. 數據按照slot存儲分布在多個節點,節點間數據共享,可動態調整數據分布。

3. 可擴展性,可線性擴展到1000個節點,節點可動態添加或刪除。

4. 高可用性,部分節點不可用時,集群仍可用。通過增加Slave做standby數據副本,能夠實現故障自動failover,節點之間通過gossip協議交換狀態信息,用投票機制完成Slave到Master的角色提升。

5. 降低運維成本,提高系統的擴展性和可用性。

不足

1. Client實現複雜,驅動要求實現Smart Client,緩存slots mapping信息並及時更新,提高了開發難度,客戶端的不成熟影響業務的穩定性。目前僅JedisCluster相對成熟,異常處理部分還不完善,比如常見的「max redirect exception」。

2. 節點會因為某些原因發生阻塞(阻塞時間大於clutser-node-timeout),被判斷下線,這種failover是沒有必要的。

3. 數據通過非同步複製,不保證數據的強一致性。

4. 多個業務使用同一套集群時,無法根據統計區分冷熱數據,資源隔離性較差,容易出現相互影響的情況。

5. Slave在集群中充當「冷備」,不能緩解讀壓力,當然可以通過SDK的合理設計來提高Slave資源的利用率。

Redis Cluster在業界有哪些探索

通過調研了解,目前業界使用Redis Cluster大致可以總結為4類:

直連型

直連型,又可以稱之為經典型或者傳統型,是官方的默認使用方式,架構圖見圖6。這種使用方式的優缺點在上面的介紹中已經有所說明,這裡不再過多重複贅述。但值得一提的是,這種方式使用Redis Cluster需要依賴Smart Client,諸如連接維護、緩存路由表、MultiOp和Pipeline的支持都需要在Client上實現,而且很多語言的Client目前都還是沒有的(關於Clients的更多介紹請參考https://redis.io/clients)。雖然Client能夠進行定製化,但有一定的開發難度,客戶端的不成熟將直接影響到線上業務的穩定性。

圖6 Redis Cluster架構

帶Proxy型

在Redis Cluster還沒有那麼穩定的時候,很多公司都已經開始探索分布式Redis的實現了,比如有基於Twemproxy或者Codis的實現,下面舉一個唯品會基於Twemproxy架構的例子(不少公司分布式Redis的集群架構都經歷過這個階段),如圖7所示。

圖7 Redis基於Twemproxy的架構實現

這種架構的優點和缺點也比較明顯。

優點:

1. 後端Sharding邏輯對業務透明,業務方的讀寫方式和操作單個Redis一致;

2. 可以作為Cache和Storage的Proxy,Proxy的邏輯和Redis資源層的邏輯是隔離的;

3. Proxy層可以用來兼容那些目前還不支持的Clients。

缺點:

1. 結構複雜,運維成本高;

2. 可擴展性差,進行擴縮容都需要手動干預;

3. failover邏輯需要自己實現,其本身不能支持故障的自動轉移;

4. Proxy層多了一次轉發,性能有所損耗。

正是因此,我們知道Redis Cluster和基於Twemproxy結構使用中各自的優缺點,於是就出現了下面的這種架構,糅合了二者的優點,盡量規避二者的缺點,架構如圖8。

圖8 Smart Proxy方案架構

目前業界Smart Proxy的方案了解到的有基於Nginx Proxy和自研的,自研的如餓了么開源部分功能的Corvus,優酷土豆是則通過Nginx來實現,滴滴也在展開基於這種方式的探索。選用Nginx Proxy主要是考慮到Nginx的高性能,包括非同步非阻塞處理方式、高效的內存管理、和Redis一樣都是基於epoll事件驅動模式等優點。優酷土豆的Redis服務化就是採用這種結構。

優點:

1. 提供一套HTTP Restful介面,隔離底層資源,對客戶端完全透明,跨語言調用變得簡單;

2. 升級維護較為容易,維護Redis Cluster,只需平滑升級Proxy;

3. 層次化存儲,底層存儲做冷熱異構存儲;

4. 許可權控制,Proxy可以通過密鑰管理白名單,把一些不合法的請求都過濾掉,並且也可以對用戶請求的超大value進行控制和過濾;

5. 安全性,可以屏蔽掉一些危險命令,比如keys *、save、flushall等,當然這些也可以在Redis上進行設置;

6. 資源邏輯隔離,根據不同用戶的key加上前綴,來實現動態路由和資源隔離;

7. 監控埋點,對於不同的介面進行埋點監控。

缺點:

1. Proxy層做了一次轉發,性能有所損耗;

2. 增加了運維成本和管理成本,需要對架構和Nginx Proxy的實現細節足夠了解,因為Nginx Proxy在批量介面調用高並發下可能會瞬間向Redis Cluster發起幾百甚至上千的協程去訪問,導致Redis的連接數或系統負載的不穩定,進而影響集群整體的穩定性。

雲服務型

這種類型典型的案例就是企業級的PaaS產品,如亞馬遜和阿里雲提供的Redis Cluster服務,用戶無需知道內部的實現細節,只管使用即可,降低了運維和開發成本。當然也有開源的產品,國內如搜狐的CacheCloud,它提供一個Redis雲管理平台,實現多種類型(Redis Standalone、Redis Sentinel、Redis Cluster)自動部署,解決Redis實例碎片化現象,提供完善統計、監控、運維功能,減少開發人員的運維成本和誤操作,提高機器的利用率,提供靈活的伸縮性,提供方便的接入客戶端,更多細節請參考:https://cachecloud.github.io。儘管這還不錯,如果是一個新業務,到可以嘗試一下,但若對於一個穩定的業務而言,要遷移到CacheCloud上則需要謹慎。如果對分布式框架感興趣的可以看下Twitter開源的一個實現Memcached和Redis的分布式緩存框架Pelikan,目前國內並沒有看到這樣的應用案例,它的官網是http://twitter.github.io/pelikan/。

圖9 CacheCloud平台架構

自研型

這種類型在眾多類型中更顯得孤獨,因為這種類型的方案更多是現象級,僅僅存在於為數不多的具有自研能力的公司中,或者說這種方案都是各公司根據自己的業務模型來進行定製化的。這類產品的一個共同特點是沒有使用Redis Cluster的全部功能,只是借鑒了Redis Cluster的某些核心功能,比如說failover和slot的遷移。作為國內使用Redis較早的公司之一,新浪微博就基於內部定製化的Redis版本研發出了微博Redis服務化系統Tribe。它支持動態路由、讀寫分離(從節點能夠處理讀請求)、負載均衡、配置更新、數據聚集(相同前綴的數據落到同一個slot中)、動態擴縮容,以及數據落地存儲。同類型的還有百度的BDRP系統。

圖10 Tribe系統架構圖

Redis Cluster運維開發最佳實踐經驗

根據公司的業務模型選擇合適的架構,適合自己的才是最好的;

做好容錯機制,當連接或者請求異常時進行連接retry或reconnect;

重試時間可設置大於cluster-node-time (默認15s),增強容錯性,減少不必要的failover;

避免產生hot-key,導致節點成為系統的短板;

避免產生big-key,導致網卡打爆和慢查詢;

設置合理的TTL,釋放內存。避免大量key在同一時間段過期,雖然Redis已經做了很多優化,仍然會導致請求變慢;

避免使用阻塞操作(如save、flushall、flushdb、keys *等),不建議使用事務;

Redis Cluster不建議使用pipeline和multi-keys操作(如mset/mget. multi-key操作),減少max redirect的產生;

當數據量很大時,由於複製積壓緩衝區大小的限制,主從節點做一次全量複製導致網路流量暴增,建議單實例容量不要分配過大或者借鑒微博的優化採用增量複製的方式來規避;

數據持久化建議在業務低峰期操作,關閉aofrewrite機制,aof的寫入操作放到bio線程中完成,解決磁碟壓力較大時Redis阻塞的問題。設置系統參數vm.overcommit_memory=1,也可以避免bgsave/aofrewrite的失敗;

client buffer參數調整

client-output-buffer-limit normal 256mb 128mb 60

client-output-buffer-limit slave 512mb 256mb 180

對於版本升級的問題,修改源碼,將Redis的核心處理邏輯封裝到動態庫,內存中的數據保存在全局變數里,通過外部程序來調用動態庫里的相應函數來讀寫數據。版本升級時只需要替換成新的動態庫文件即可,無須重新載入數據,可毫秒級完成;

對於實現異地多活或實現數據中心級災備的要求(即實現集群間數據的實時同步),可以參考搜狐的實現:Redis Cluster => Redis-Port => Smart proxy => Redis Cluster;

從Redis 4.2的Roadmap來看,更值得期待(詳情:https://gist.github.com/antirez/a3787d538eec3db381a41654e214b31d):

加速key->hashslot的分配

更好更多的數據中心存儲

redis-trib的C代碼將移植到redis-cli,瘦身包體積

集群的備份/恢復

非阻塞的Migrate

更快的resharding

隱藏一個只Cache模式,當沒有Slave時,Masters當在有一個失敗後能夠自動重新分配slot

Cluster API和Redis Modules的改進,並且Disque分布式消息隊列將作為Redis Module加入Redis。

致謝:感謝好友陳群、李航和劉東輝的協助審稿和寶貴建議。

作者簡介

張冬洪,微博研發中心高級DBA,Redis中國用戶組主席,多年Linux和資料庫運維經驗,專註於MySQL和NoSQL架構設計與運維以及自動化平台的開發;目前在微博主要負責Feed核心系統相關業務的資料庫運維和業務保障工作。

點擊展開全文

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 CSDN 的精彩文章:

5個你必須知道的Docker實用工具
物聯網浪潮之下,前端工程師如何迎刃而上?
專訪架構師陳波:微博近幾年的架構演進和架構師的技能素養
RocketMQ開源二三事,偵破萬億級數據容量背後的架構實踐
淺談分布式事務控制在銀行應用的實現

TAG:CSDN |

您可能感興趣

Learning Memory Access Patterns,資料庫+機器學習探索
Leap Motion探索AR/VR新世界形態:Mirrorworlds
探索TimelinePlayableAPI,讓Timeline為所欲為
探索義大利各大區之美-巴西利卡塔 Alla scoperta delle Regioni Italiane-Basilicata
上周藝術探索回顧-Knights,Princess and Dragons
探店#Patisserie des Alpes一起來探索阿爾卑斯吧!
演員萬茜化身Pierre Cardin original collection品牌摯友,攜手探索精彩未來
DOM探索之-DOM的nodeType、nodeName、nodeValue
首席運營官高盛探索Crypto Derivatives
Oculus CTO:在Oculus Quest探索手勢識別
「白泥潔凈面膜」 ×Philosophy「凈透天使」Jessica鄭秀妍 與Jessica鄭秀妍一起,探索philosophy的奇蹟之美
法國 Palais de la découverte 探索宮80周年視覺設計
Adobe探索VR繪畫系統Multiplanes,為用戶解決VR繪畫挑戰
本周藝術探索-Rompin』 Robots
convergencias展覽 深入探索古巴設計
深入GlobalFoundries的晶元前沿領域探索之路
Facebook正探索Oculus Quest多賬號支持
【遊戲推薦】探索世界的回合制Rougelike卡牌RPG:Deck Hunter
Oculus CTO卡馬克:正大力探索Oculus Quest的手指追蹤
DOM探索之-domReady