項目經理:你來設計一下Redis 故障轉移、高可用的方案
Redis 大家都不陌生,就算是沒用過,也都聽説過了。
作為最廣泛使用的 KV 內存數據庫之一,在當今的 大流量時代 ,單機模式略顯單薄,免不了要有一些 拓展 的方案。
筆者下文會對各種方案進行介紹,並且給出 場景 , 實現 等等概述,還會提到一些新手常見的誤區。
正文
先從基礎的拓展方式開始,這樣更便於理解較高級的模式。
ps: 本文背景是以筆者落筆時官網最新穩定版 5.0.8 為準,雖然還沒寫完就變成了6.0.1。
分區
概述
分區 (Partitioning)是一種最為簡單的拓展方式。
在我們面臨 單機 的 存儲空間 瓶頸時,第一點就能想到像傳統的關係型數據庫一樣,進行數據分區。
或者假設手中有 N 台機器可以作為Redis服務器 所有機器內存總和有256G, 而客户端正好也需要一個大內存的存儲空間。
我們除了可以把內存條都拆下來焊到一個機器上,也可以選擇分區使用,這樣又拓展了計算能力。
單指 分區 來講,即將全部數據分散在多個Redis實例中,每個實例不需要關聯,可以是完全獨立的。
使用方式
-
客户端處理 和傳統的數據庫分庫分表一樣,可以從 key 入手,先進行計算,找到對應數據存儲的實例在進行操作。 範圍角度 ,比如orderId:1~orderId:1000放入實例1,orderId:1001~orderId:2000放入實例2... 哈希計算 ,就像我們的 hashmap 一樣,用hash函數加上位運算或者取模,高級玩法還有一致性Hash等操作,找到對應的實例進行操作
-
使用代理中間件 我們可以開發獨立的代理中間件,屏蔽掉處理數據分片的邏輯,獨立運行。當然也有他人已經造好的輪子,Redis也有優秀的代理中間件,譬如Twemproxy,或者codis,可以結合場景選擇是否使用。
缺點
-
無緣多key操作 ,key都不一定在一個實例上,那麼多key操作或者多key事務自然是不支持。
-
維護成本 ,由於每個實例在物理和邏輯上,都屬於單獨的一個節點,缺乏統一管理。
-
靈活性有限 ,範圍分片還好,比如hash+MOD這種方式,如果想 動態 調整Redis實例的數量,就要考慮大量數據遷移,這就非常麻煩了。
同為開發者,深知我們雖然總能“曲線救國”的完成一些當前環境不支持的功能,但是總歸要麻煩一些。
主從
概述數據遷移
常説的 主從 (Master-Slave),也就是複製(Replication)方式,怎麼稱呼都可以。
同上面的 分區 一樣,也是Redis高可用架構的基礎,新手可能會誤以為這類基礎模式即是“高可用”,這並不是十分正確的。
分區暫時能解決 單點 無法容納的 數據量問題 ,但是一個Key還是隻在一個實例上,在大流量時代顯得不那麼可靠。
主從 就是另一個緯度的拓展,節點將數據同步到 從 節點,就像將實例“ 分身 ”了一樣,可靠性又提高了不少。
[
圖畫的有些誇張了,主要還是想體現 結構靈活 ,是一主一從,還是一主多從,還是一主多從多從... 看你心情
有了“實例分身”,自然就可以做 讀寫分離 ,將讀流量均攤在各個從節點。
使用方式
高手雲集 的時代,聊天軟件難免要備上這麼一張表情包。
這表情包和 使用方式 有什麼關係呢?首先看看使用方式:
-
作為主節點的Redis實例,並不要求配置任何參數,只需要正常啟動
-
作為從節點的實例,使用配置文件或命令方式
REPLICAOF 主節點Host 主節點port
即可完成主從配置
是不是和表情包一樣,“dalao”沒動,我去“ 抱大腿 ”。
這樣一個主從最小配置就完成了,主從實例即可對外提供服務。
命令裏的“主節點”是相對的,slave也可以抱slave大腿,也就是上文提到的 結構靈活 。
缺點
-
slave節點都是 只讀 的,如果 寫流量 大的場景,就有些力不從心了。那我把slave節點 只讀 關掉不就行了?當然不行,數據複製是由主到從,從節點獨有數據同步不到主節點,數據就不一致了。
-
故障轉移 不友好,主節點掛掉後,寫處理就無處安放,需要 手工 的設定新的主節點,如使用
REPLICAOF no one
(誰大腿我都不抱了) 晉升為主節點,再梳理其他slave節點的新主配置,相對來説比較麻煩。
哨兵
概述
主從 的手工故障轉移,肯定讓人很難接受,自然就出現了高可用方案- 哨兵 (Sentinel)。
我們可以在主從架構不變的場景,直接加入 Redis Sentinel ,對節點進行 監控 ,來完成自動的 故障發現 與 轉移 。
並且還能夠充當 配置提供者 ,提供主節點的信息,就算髮生了故障轉移,也能提供正確的地址。
哨兵 本身也是Redis實例的一種,但不作為數據存儲方使用,啟動命令也是不一樣的。
雖然圖有些複雜,看起來像要召喚光能使者。
其實實際使用起來是很便捷的。
使用方式
Sentinel 的最小配置,一行即可:
sentinel monitor <主節點別名> <主節點host> <主節點端口> <票數>
只需要配置master即可,然後用
redis-sentinel <配置文件>
命令即可啟用。
Redis官網提到的“ 最小配置 ”是如下所示,除了上面提到的一行,還有其它的一些配置:
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 60000
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1
sentinel monitor resque 192.168.1.3 6380 4
sentinel down-after-milliseconds resque 10000
sentinel failover-timeout resque 180000
sentinel parallel-syncs resque 5
這是因為官網加了一個修飾詞,是“ 典型的最小配置 ”,把重要參數和 多主 的例子都寫出來了,照顧大家CV大法的時候,不要忘記重要參數,其實都是有默認值的。
正如該例所示,設置 主節點別名
就是為了監控 多主
的時候,與其額外配置項能夠與其對應, 以及sentinel一些命令,如
SENTINEL get-master-addr-by-name
就要用到別名了。
哨兵數量建議在三個以上且為奇數,在Redis官網也提到了各種情況的“佈陣”方式,非常值得參考。
更多
既然是高可用方案,並非有嚴格意義上的“缺點”,還需配合使用場景進行考量。
-
故障轉移期間短暫的不可用,但其實官網的例子也給出了
parallel-syncs
參數來指定並行的同步實例數量,以免全部實例都在同步出現整體不可用的情況,相對來説要比手工的故障轉移更加方便。 -
分區邏輯需要自定義處理,雖然解決了 主從 下的高可用問題,但是Sentinel並沒有提供分區解決方案,還需開發者考慮如何建設。
-
既然是還是主從,如果異常的寫流量搞垮了主節點,那麼自動的“ 故障轉移 ”會不會變成自動“ 災難傳遞 ”,即slave提升為Master之後掛掉,又進行提升又被掛掉。不過最後這點也是筆者猜測,並沒有聽説過出現這種案例,可不必深究。
集羣
概述
Redis Cluster 是官方在 3.0 版本後推出的分佈式方案。
對開發者而言,“官方支持”一詞是大概率非常美好的,小到issue,大到feature。自定義去解決問題,成本總是要高一些。
有了官方的正式集羣方案,從 請求路由、故障轉移、彈性伸縮 幾個緯度的使用上,將更為容易。
Cluster 不同於哨兵,是支持分區的。有説法Cluster是哨兵的升級,這是不嚴謹的。
二者緯度不一樣,如果因為Cluster也有故障轉移的功能,就説它是哨兵的升級款,略顯牽強。
Cluster
在分區管理上,使用了“ 哈希槽
”(hash slot)這麼一個概念,一共有 16384
個槽位,每個實例負責一部分 槽
,通過
CRC16(key)&16383
這樣的公式,計算出來key所對應的槽位。
雖然在 節點 和 key 二者中又引入了 槽 的概念,看起來不易理解,實際上因為顆粒度更細了,減少了節點的擴容和收縮難度,相比傳統策略還是很有優勢。
當然,“槽”是虛擬的概念,節點自身去維護“槽”的關係,並不是要真正下載啟動個“槽服務”在跑。
使用方式
Redis的各種玩法,都是從配置文件着手,集羣也不例外。
cluster-enabled yes
cluster-config-file "redis-node.conf"
關鍵配置簡潔明瞭,有兩步
-
開啟集羣
-
指定集羣配置文件
集羣配置文件(cluster-config-file)為內部使用,可以不去指定,Redis會幫助創建一個。啟動還是普通的方式
redis-server redis.conf
首先以集羣方式啟動了N台Redis實例,這當然還沒完事。
接下來的步驟筆者稱為“ 牽線搭橋分配槽 ”,聽起來還算順口。
“牽線搭橋分配槽”的方式也在不斷升級,從直接用原始命令來處理,到使用腳本,以及現在的Redis-cli官方支持,使用哪種方式都可以。
redis-cli --cluster create 127.0.0.1:7000 127.0.0.1:7001 \
127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 \
--cluster-replicas 1
上方的命令即是Redis官網給出的redis-cli的方式用法,一行命令完成“三主三從”以及自動分配槽的操作。
這樣集羣就搭建完成了,當然,使用官方提供的check命令檢查一下,也是有必要的。
redis-cli --cluster check 127.0.0.1:7001
更多
-
雖然是對分區良好支持,但也有一些分區的老問題,譬如:如果不在同一個“槽”的數據,是沒法使用類似mset的 多鍵操作 。
-
在select命令頁有提到, 集羣模式下只能使用一個庫,雖然平時一般也是這麼用的,但是要了解一下。
-
運維上也要謹慎,俗話説得好,“ 使用越簡單底層越複雜 ”,啟動搭建是很方便,使用時面對帶寬消耗,數據傾斜等等具體問題時,還需人工介入,或者研究合適的配置參數。
結尾
趣談
在寫“主從”方案的時候,發現有一個有趣的事情:
筆者開始是記得主從的關鍵命令是
SLAVEOF
,後來查閲官方的時候,發現命令已經更改為
REPLICAOF
,雖然
SLAVEOF
還能用。
官網的一些描述詞彙,有的地方還是Slave,也有些是用Replication。
好奇的筆者查了一下相關的資料,並看了些Redis作者antirez的有關此時博客,發現已經是兩年前的事情了。
其實就是“Slave”這個變量名給了一些人機會,藉此“噴”了一波作者,作者也做出了一部分妥協。
有興趣的盆友可以自己搜搜看,技術外的東西就不做評價了,看個樂呵就行。
筆者的主要目的還是:看官方文檔的時候,別讓不同的“詞彙”迷惑了。
來源 | http://juejin.cn/post/6844904147943161869
回覆 【 乾貨 】 獲取精選乾貨視頻教程
回覆 【 加羣 】 加入疑難問題攻堅交流羣
回覆 【 mat 】 獲取 內存溢出問題分析 詳細文檔教程
回覆 【 賺錢 】 獲取用java寫一個能賺錢的微信機器人
回覆 【 副業 】 獲取程序員副業攻略一份
戳這兒
- 被問Linux命令su 和sudo的區別?懵了
- MySQL 定時備份數據庫(非常全),值得收藏!
- 這可能是給Spring Boot Starter 講的最清楚的一次了
- 支付寶項目組使用的支付加密規則梳理,寫的太好了!
- Elasticsearch 快速檢索的祕訣
- 開源分佈式定時任務框架技術選型
- 2.3W字,這可能是把Nginx講得最全面的一篇文章了,建議收藏備用
- SpringBoot Redis搭建支撐10w 人的秒殺搶單系統!
- SpringBoot MySQL實現讀寫分離就這麼簡單,幾步搞定!
- ElasticSearch(ik分詞器) SpringBoot站內全文搜索解決方案
- Spring Boot Redis 三連招:Jedis,Redisson,Lettuce
- (建議收藏)服務器宕機,效率排查攻略V2.0
- Redis高可用解決方案:sentinel(哨兵模式)和集羣
- java總監寫的架構設計説明書,按這個思路去評審沒問題吧?
- 當美團大佬遇到Spring Boot “內存泄漏”?解決方案亮了
- ElasticSearch搜索引擎原理,都給你整理好了
- 面試官:這份Spring Boot 核心知識點總結收好了!
- 1.6w字講清楚:Sharding-Jdbc 實現讀寫分離 分庫分表!
- 項目經理:Redis緩存都會用,那使用後的效益和成本怎麼估算?
- Java中clone( )和new效率哪個更高?