Redis內(nèi)存又不夠用了?教你幾種集群方案輕松甩掉存儲(chǔ)難題
Redis,一款技術(shù)研發(fā)者們耳熟能詳?shù)膬?nèi)存數(shù)據(jù)庫。作為數(shù)據(jù)庫,存儲(chǔ)數(shù)據(jù)的容量都是有限的,不能超過主機(jī)內(nèi)存的大小。通常而言,一臺(tái)主機(jī)服務(wù)器的內(nèi)存只有十幾G,較大可達(dá)100G或200G。
為了解決Redis存儲(chǔ)瓶頸問題,各大企業(yè)紛紛開始尋找解決方案,將數(shù)據(jù)分片(sharding)存儲(chǔ)在多個(gè)Redis實(shí)例之中,每一個(gè)分片就是一個(gè)Redis實(shí)例,然后實(shí)現(xiàn)多個(gè)Redis實(shí)例協(xié)同運(yùn)行。這就是Redis集群原理。本篇將圍繞Redis集群方案展開重點(diǎn)介紹。
Redis集群實(shí)現(xiàn)方式:
- 分區(qū),將數(shù)據(jù)分割劃分到多個(gè)Redis實(shí)例中去,然后保證每個(gè)實(shí)例只保存key的一個(gè)子集;
- 通過多臺(tái)計(jì)算機(jī)的內(nèi)存和值構(gòu)造更大的數(shù)據(jù)庫;
- 通過多臺(tái)計(jì)算機(jī)擴(kuò)展計(jì)算能力;
- 通過多臺(tái)計(jì)算機(jī)機(jī)和網(wǎng)絡(luò)適配,擴(kuò)展網(wǎng)絡(luò)寬帶。
集群的實(shí)現(xiàn)方式:
- 客戶端分片
- 基于代理的分片
- 路由查詢
下面我們對三種實(shí)現(xiàn)方式展開介紹:
客戶端分片
客戶端分片就是將分片工作放在業(yè)務(wù)程序端實(shí)現(xiàn),程序代碼根據(jù)Redis客戶端預(yù)先定義好的路由規(guī)則,直接對不同的Redis實(shí)例進(jìn)行分布式訪問,最終再把結(jié)果匯集在一起。
這種方案的優(yōu)勢就在于所有邏輯都是可以控制的,沒有第三方中間件干預(yù),開發(fā)人員很清楚如何實(shí)現(xiàn)分片及路由規(guī)則,實(shí)現(xiàn)方法完全由自己掌控。
但是客戶端分片方案的弊端也是令開發(fā)者也是十分懊惱的。由于客戶端分片方案是一種靜態(tài)的分片方案,無論是增加或是減少Redis實(shí)例的數(shù)量,都必須要開發(fā)者手動(dòng)調(diào)整分片程序,對開發(fā)者的依賴很強(qiáng);其次在運(yùn)維上,該方案運(yùn)維性較差,一旦集群數(shù)據(jù)出現(xiàn)問題,就需要開發(fā)人員和運(yùn)維人員共同解決,在不同的客戶端程序中,維護(hù)相同的分片邏輯成本很大,需要消耗巨大的開發(fā)成本才能保證兩套業(yè)務(wù)系統(tǒng)分片邏輯一致。所以,客戶端分片方案并不適合中小型的企業(yè)使用。
基于代理的分片
基于代理分片就是客戶端發(fā)送請求到一個(gè)代理,由代理來解析客戶端的數(shù)據(jù),再將請求轉(zhuǎn)發(fā)到正確的節(jié)點(diǎn),最終將結(jié)果回復(fù)給客戶端。常用的基于代理的分片方案有兩種,Twemproxy、codis。
Twemproxy
Twemproxy是一款由Twitter開源的redis proxy方案,在Twitter、Yahoo都有使用。當(dāng)Twemproxy工作時(shí),Redis客戶端會(huì)把請求發(fā)送到Twemproxy,Twemproxy會(huì)使用一致性hash算法,根據(jù)路由規(guī)則發(fā)送正確的Redis實(shí)例,最后Twemproxy再把結(jié)果返給客戶端,從而實(shí)現(xiàn)Redis集群。
由于Twemproxy是單線程方案,所以只能使用單核cpu,如果前端含keepalive或haproxy相關(guān)代理,可以為Twemproxy做1+1準(zhǔn)備。
當(dāng)Twemproxy應(yīng)用于多臺(tái)Redis服務(wù)器時(shí),那么實(shí)現(xiàn)的性能只能達(dá)到單臺(tái)Redis服務(wù)器80%,剩余20%性能損耗。Redis-Sentinel是Redis官方推薦的一種高可用性解決方案,當(dāng)用Redis做Master-slave的高可用方案時(shí),如果Master宕機(jī)了,Twemproxy會(huì)訂閱Sentinel,完成主備切換。由于Redis-sentinel本身是一個(gè)獨(dú)立運(yùn)行的進(jìn)程,它能監(jiān)控多個(gè)master-slave集群,發(fā)現(xiàn)master宕機(jī)后可以進(jìn)行自動(dòng)切換。
Twemproxy優(yōu)點(diǎn):
- 支持Redis和memcached兩種集群代理;
- 后端Redis和memcached無需任何改動(dòng),只需要提供IP和端口給Twemproxy即可,操作簡單;
- 支持無效Redis實(shí)例的自動(dòng)刪除;
- 支持狀態(tài)監(jiān)控......
Twemproxy不足:
- 無法動(dòng)態(tài)擴(kuò)容,如果需要擴(kuò)容功能,必須研發(fā)人員手動(dòng)遷移,比較繁瑣;
- 由于Redis客戶端的請求都需要經(jīng)過Twemproxy才能到達(dá)Redis服務(wù)器,期間難免會(huì)產(chǎn)生性能損失;
- 無法平滑地?cái)U(kuò)容/縮容,對于運(yùn)維人員來說,如果業(yè)務(wù)需要增加Redis實(shí)例,工作量會(huì)非常大......
Codis
Codis是由豌豆莢于2014年11月在GitHub上開源,基于Go和C語言,支持平滑增加Redis實(shí)例的集群解決方案。使用Codis時(shí),設(shè)置好下屬的Redis實(shí)例,在需要連接Redis的地方改為連接Codis,之后Codis會(huì)以一個(gè)代理的身份接受請求,并使用一致性hash算法,將請求轉(zhuǎn)接到具體Redis,最后再將結(jié)果返回到Codis。作為基于代理的分片,功能與Twemproxy類似。
Codis主要包含四大組件Codis Proxy(codis proxy)、Codis Manager(codisconfig)、Codis Redis(codis-server)和ZooKeeper,每一個(gè)組件都可以進(jìn)行動(dòng)態(tài)擴(kuò)容。
Codis Proxy:客戶端連接到Redis代理服務(wù),本身已實(shí)現(xiàn)了Redis協(xié)議,Redis客戶端連接到Codis Proxy可以進(jìn)行各種操作。Codis Proxy是無狀態(tài)的,一個(gè)業(yè)務(wù)可以通過Keepalived等負(fù)載均衡軟件部署多個(gè)Codis Proxy;
Codisconfig:Codisconfig是Codis的管理工具,支持添加/刪除Redis節(jié)點(diǎn)、添加/刪除Proxy節(jié)點(diǎn)、發(fā)起數(shù)據(jù)遷移等操作。另外Codisconfig自帶http server,里面集成一個(gè)管理界面,運(yùn)維人員可以在瀏覽器上觀察Codis集群的運(yùn)行狀態(tài)并進(jìn)行相關(guān)操作;
Codis Redis:Codis Redis基于 redis-2.8.21 分支開發(fā),是Codis項(xiàng)目維護(hù)的一個(gè)Redis分支,其中加入了slot支持和原子數(shù)據(jù)遷移指令;
ZooKeeper:Codis通過ZooKeeper來存放數(shù)據(jù)路由表和Codis Proxy節(jié)點(diǎn)的原信息,Codisconfig發(fā)起的命令都會(huì)通過ZooKeeper同步到各存活的Codis Proxy節(jié)點(diǎn)。
路由查詢
路由查詢是指將任務(wù)請求發(fā)送到任意節(jié)點(diǎn),接收到請求的節(jié)點(diǎn)會(huì)將查詢請求發(fā)送到正確的節(jié)點(diǎn)上執(zhí)行任務(wù)。在Redis集群方案中使用的路由查詢方案有Redis cluster。
Redis Cluster由Redis官方推出,是一種服務(wù)器Sharding技術(shù),3.0版本開始正式提供,可線性擴(kuò)展到1000個(gè)節(jié)點(diǎn)。在Redis Cluster中,Sharding將所有Key映射到slot中,slot個(gè)數(shù)一共16384個(gè)。Redis集群中,每個(gè)節(jié)點(diǎn)都會(huì)負(fù)責(zé)16384個(gè)slot中的一部分。當(dāng)動(dòng)態(tài)添加或減少節(jié)點(diǎn)時(shí),需要將16384個(gè)slot重做分配,slot中對應(yīng)的Key也要做遷移。這項(xiàng)工作目前是需要人工介入手動(dòng)操作的。在使用Redis Cluster時(shí),要確保16384個(gè)slot對應(yīng)節(jié)點(diǎn)都能正常工作,如果有一個(gè)節(jié)點(diǎn)發(fā)生故障,整個(gè)集群都會(huì)無法工作。
為了增加集群的可訪問性,Redis官方推薦將節(jié)點(diǎn)配置成主從結(jié)構(gòu)(一個(gè)master主節(jié)點(diǎn)掛多個(gè)salve從節(jié)點(diǎn))如果主節(jié)點(diǎn)失效,Redis Cluster會(huì)根據(jù)選舉算法從slave節(jié)點(diǎn)中選擇一個(gè)上升為主節(jié)點(diǎn),整個(gè)集群繼續(xù)對外提供服務(wù)。
使用Redis cluster時(shí),由于官方并未提供圖形管理工具,所以運(yùn)維比較復(fù)雜。而且集群管理與數(shù)據(jù)存儲(chǔ)上存在耦合,一旦集群管理出現(xiàn)問題,整個(gè)Redis都需要升級(jí)整合。Redis Cluster自2015年發(fā)布以來,成功使用的企業(yè)還并不是很多。