1 題記
Redis 是一個(gè)開(kāi)源的使用 ANSI C 語(yǔ)言編寫(xiě)、支持網(wǎng)絡(luò)瓮增、可基于內(nèi)存亦可持久化的日志型怎棱、Key-Value 數(shù)據(jù)庫(kù),并提供多種語(yǔ)言的 API绷跑。
如今拳恋,互聯(lián)網(wǎng)業(yè)務(wù)的數(shù)據(jù)正以更快的速度在增長(zhǎng),數(shù)據(jù)類(lèi)型越來(lái)越豐富砸捏,這對(duì)數(shù)據(jù)處理的速度和能力提出了更高要求谬运。Redis 是一種開(kāi)源的內(nèi)存非關(guān)系型數(shù)據(jù)庫(kù),給開(kāi)發(fā)人員帶來(lái)的體驗(yàn)是顛覆性的带膜。在自始至終的設(shè)計(jì)過(guò)程中吩谦,都充分考慮高性能,這使得 Redis 成為當(dāng)今速度最快的 NoSQL 數(shù)據(jù)庫(kù)膝藕。
考慮高性能的同時(shí),高可用也是很重要的考慮因素咐扭“磐欤互聯(lián)網(wǎng) 7x24 無(wú)間斷服務(wù)滑废,在故障期間以最快的速度 Failover,能給企業(yè)帶來(lái)最小的損失袜爪。
那么蠕趁,在實(shí)際應(yīng)用中,都有哪些高可用架構(gòu)呢辛馆?架構(gòu)之間有何優(yōu)劣俺陋?我們應(yīng)該怎么取舍?有哪些最佳實(shí)踐昙篙?
二腊状、Sentinel (哨兵)原理
在講解 Redis 高可用方案之前,我們先來(lái)看看 Redis Sentinel 原理(https://redis.io/topics/sentinel)是怎么樣的苔可。
Sentinel 集群通過(guò)給定的配置文件發(fā)現(xiàn) master缴挖,啟動(dòng)時(shí)會(huì)監(jiān)控 master。通過(guò)向 master 發(fā)送 info 信息獲得該服務(wù)器下面的所有從服務(wù)器焚辅。
Sentinel 集群通過(guò)命令連接向被監(jiān)視的主從服務(wù)器發(fā)送 hello 信息 (每秒一次)映屋,該信息包括 Sentinel 本身的 IP、端口同蜻、id 等內(nèi)容棚点,以此來(lái)向其他 Sentinel 宣告自己的存在。
Sentinel 集群通過(guò)訂閱連接接收其他 Sentinel 發(fā)送的 hello 信息湾蔓,以此來(lái)發(fā)現(xiàn)監(jiān)視同一個(gè)主服務(wù)器的其他 Sentinel乙濒;集群之間會(huì)互相創(chuàng)建命令連接用于通信,因?yàn)橐呀?jīng)有主從服務(wù)器作為發(fā)送和接收 hello 信息的中介卵蛉,Sentinel 之間不會(huì)創(chuàng)建訂閱連接颁股。
Sentinel 集群使用 ping 命令來(lái)檢測(cè)實(shí)例的狀態(tài),如果在指定的時(shí)間內(nèi)(down-after-milliseconds)沒(méi)有回復(fù)或則返回錯(cuò)誤的回復(fù)傻丝,那么該實(shí)例被判為下線(xiàn)甘有。
當(dāng) failover 主備切換被觸發(fā)后,failover 并不會(huì)馬上進(jìn)行葡缰,還需要 Sentinel 中的大多數(shù) Sentinel 授權(quán)后才可以進(jìn)行 failover亏掀,即進(jìn)行 failover 的 Sentinel 會(huì)去獲得指定 quorum 個(gè)的 Sentinel 的授權(quán),成功后進(jìn)入 ODOWN 狀態(tài)泛释。如在 5 個(gè) Sentinel 中配置了 2 個(gè) quorum滤愕,等到 2 個(gè) Sentinel 認(rèn)為 master 死了就執(zhí)行 failover。
Sentinel 向選為 master 的 slave 發(fā)送 SLAVEOF NO ONE 命令怜校,選擇 slave 的條件是 Sentinel 首先會(huì)根據(jù) slaves 的優(yōu)先級(jí)來(lái)進(jìn)行排序间影,優(yōu)先級(jí)越小排名越靠前。如果優(yōu)先級(jí)相同茄茁,則查看復(fù)制的下標(biāo)魂贬,哪個(gè)從 master 接收的復(fù)制數(shù)據(jù)多巩割,哪個(gè)就靠前。如果優(yōu)先級(jí)和下標(biāo)都相同付燥,就選擇進(jìn)程 ID 較小的宣谈。
Sentinel 被授權(quán)后,它將會(huì)獲得宕掉的 master 的一份最新配置版本號(hào) (config-epoch)键科,當(dāng) failover 執(zhí)行結(jié)束以后闻丑,這個(gè)版本號(hào)將會(huì)被用于最新的配置,通過(guò)廣播形式通知其它 Sentinel勋颖,其它的 Sentinel 則更新對(duì)應(yīng) master 的配置嗦嗡。
1 到 3 是自動(dòng)發(fā)現(xiàn)機(jī)制:
以 10 秒一次的頻率,向被監(jiān)視的 master 發(fā)送 info 命令牙言,根據(jù)回復(fù)獲取 master 當(dāng)前信息酸钦。
以 1 秒一次的頻率,向所有 redis 服務(wù)器咱枉、包含 Sentinel 在內(nèi)發(fā)送 PING 命令卑硫,通過(guò)回復(fù)判斷服務(wù)器是否在線(xiàn)。
以 2 秒一次的頻率蚕断,通過(guò)向所有被監(jiān)視的 master欢伏,slave 服務(wù)器發(fā)送當(dāng)前 Sentinel master 信息的消息。
4 是檢測(cè)機(jī)制亿乳,5 和 6 是 failover 機(jī)制硝拧,7 是更新配置機(jī)制。[1]
三葛假、Redis 高可用架構(gòu)
講解完 Redis Sentinel 原理之后障陶,接下來(lái)講解常用的 Redis高可用架構(gòu)。
Redis Sentinel 集群 + 內(nèi)網(wǎng) DNS + 自定義腳本
Redis Sentinel 集群 + VIP + 自定義腳本
封裝客戶(hù)端直連 Redis Sentinel 端口
JedisSentinelPool聊训,適合 Java
PHP 基于 phpredis 自行封裝
Redis Sentinel 集群 + Keepalived/Haproxy
Redis M/S + Keepalived
Redis Cluster
Twemproxy
Codis
接下來(lái)配合圖文逐個(gè)講解抱究。
1、Redis Sentinel 集群 + 內(nèi)網(wǎng) DNS + 自定義腳本
Redis Sentinel 集群 + 內(nèi)網(wǎng) DNS + 自定義腳本
上圖是已經(jīng)在線(xiàn)上環(huán)境應(yīng)用的方案带斑。底層是 Redis Sentinel 集群鼓寺,代理著 Redis 主從,Web 端連接內(nèi)網(wǎng) DNS 提供服務(wù)勋磕。內(nèi)網(wǎng) DNS 按照一定的規(guī)則分配妈候,比如 xxxx.redis.cache/queue.port.xxx.xxx,第一個(gè)段表示業(yè)務(wù)簡(jiǎn)寫(xiě)挂滓,第二個(gè)段表示這是 Redis 內(nèi)網(wǎng)域名苦银,第三個(gè)段表示 Redis 類(lèi)型,cache 表示緩存,queue 表示隊(duì)列墓毒,第四個(gè)段表示 Redis 端口吓揪,第五亲怠、第六個(gè)段表示內(nèi)網(wǎng)主域名所计。
當(dāng)主節(jié)點(diǎn)發(fā)生故障,比如機(jī)器故障团秽、Redis 節(jié)點(diǎn)故障或者網(wǎng)絡(luò)不可達(dá)主胧,Sentinel 集群會(huì)調(diào)用 client-reconfig-script 配置的腳本,修改對(duì)應(yīng)端口的內(nèi)網(wǎng)域名习勤。對(duì)應(yīng)端口的內(nèi)網(wǎng)域名指向新的 Redis 主節(jié)點(diǎn)踪栋。
優(yōu)點(diǎn):
秒級(jí)切換,在 10s 內(nèi)完成整個(gè)切換操作
腳本自定義图毕,架構(gòu)可控
對(duì)應(yīng)用透明夷都,前端不用擔(dān)心后端發(fā)生什么變化
缺點(diǎn):
維護(hù)成本略高,Redis Sentinel 集群建議投入 3 臺(tái)機(jī)器以上
依賴(lài) DNS予颤,存在解析延時(shí)
Sentinel 模式存在短時(shí)間的服務(wù)不可用
服務(wù)通過(guò)外網(wǎng)訪(fǎng)問(wèn)不可采用此方案
2囤官、Redis Sentinel 集群 + VIP + 自定義腳本
Redis Sentinel 集群 + VIP + 自定義腳本
此方案和上一個(gè)方案相比,略有不同蛤虐。第一個(gè)方案使用了內(nèi)網(wǎng) DNS党饮,第二個(gè)方案把內(nèi)網(wǎng) DNS 換成了虛擬 IP。底層是 Redis Sentinel 集群驳庭,代理著 Redis 主從刑顺,Web 端通過(guò) VIP 提供服務(wù)。在部署 Redis 主從的時(shí)候饲常,需要將虛擬 IP 綁定到當(dāng)前的 Redis 主節(jié)點(diǎn)蹲堂。當(dāng)主節(jié)點(diǎn)發(fā)生故障,比如機(jī)器故障贝淤、Redis 節(jié)點(diǎn)故障或者網(wǎng)絡(luò)不可達(dá)柒竞,Sentinel 集群會(huì)調(diào)用 client-reconfig-script 配置的腳本,將 VIP 漂移到新的主節(jié)點(diǎn)上霹娄。
優(yōu)點(diǎn):
秒級(jí)切換能犯,在 5s 內(nèi)完成整個(gè)切換操作
腳本自定義,架構(gòu)可控
對(duì)應(yīng)用透明犬耻,前端不用擔(dān)心后端發(fā)生什么變化
缺點(diǎn):
維護(hù)成本略高踩晶,Redis Sentinel 集群建議投入 3 臺(tái)機(jī)器以上
使用 VIP 增加維護(hù)成本,存在 IP 混亂風(fēng)險(xiǎn)
Sentinel 模式存在短時(shí)間的服務(wù)不可用
3.3 封裝客戶(hù)端直連 Redis Sentinel 端口
3枕磁、封裝客戶(hù)端直連 Redis Sentinel 端口
部分業(yè)務(wù)只能通過(guò)外網(wǎng)訪(fǎng)問(wèn) Redis渡蜻,上述兩種方案均不可用,于是衍生出了這種方案。Web 使用客戶(hù)端連接其中一臺(tái) Redis Sentinel 集群中的一臺(tái)機(jī)器的某個(gè)端口茸苇,然后通過(guò)這個(gè)端口獲取到當(dāng)前的主節(jié)點(diǎn)排苍,然后再連接到真實(shí)的 Redis 主節(jié)點(diǎn)進(jìn)行相應(yīng)的業(yè)務(wù)員操作。需要注意的是学密,Redis Sentinel 端口和 Redis 主節(jié)點(diǎn)均需要開(kāi)放訪(fǎng)問(wèn)權(quán)限淘衙。如果前端業(yè)務(wù)使用 Java,有 JedisSentinelPool 可以復(fù)用腻暮;如果前端業(yè)務(wù)使用 PHP彤守,可以在 phpredis 的基礎(chǔ)上做二次封裝。
優(yōu)點(diǎn):
服務(wù)探測(cè)故障及時(shí)
DBA 維護(hù)成本低
缺點(diǎn):
依賴(lài)客戶(hù)端支持 Sentinel
Sentinel 服務(wù)器和 Redis 節(jié)點(diǎn)需要開(kāi)放訪(fǎng)問(wèn)權(quán)限
對(duì)應(yīng)用有侵入性
4哭靖、Redis Sentinel 集群 + Keepalived/Haproxy
Redis Sentinel 集群 + Keepalived/Haproxy
底層是 Redis Sentinel 集群具垫,代理著 Redis 主從,Web 端通過(guò) VIP 提供服務(wù)试幽。當(dāng)主節(jié)點(diǎn)發(fā)生故障筝蚕,比如機(jī)器故障、Redis 節(jié)點(diǎn)故障或者網(wǎng)絡(luò)不可達(dá)铺坞,Redis 之間的切換通過(guò) Redis Sentinel 內(nèi)部機(jī)制保障起宽,VIP 切換通過(guò) Keepalived 保障。
優(yōu)點(diǎn):
秒級(jí)切換
對(duì)應(yīng)用透明
缺點(diǎn):
維護(hù)成本高
存在腦裂
Sentinel 模式存在短時(shí)間的服務(wù)不可用
5康震、Redis M/S + Keepalived
Redis M/S + Keepalived
此方案沒(méi)有使用到 Redis Sentinel燎含。此方案使用了原生的主從和 Keepalived,VIP 切換通過(guò) Keepalived 保障腿短,Redis 主從之間的切換需要自定義腳本實(shí)現(xiàn)屏箍。
優(yōu)點(diǎn):
秒級(jí)切換
對(duì)應(yīng)用透明
部署簡(jiǎn)單,維護(hù)成本低
缺點(diǎn):
需要腳本實(shí)現(xiàn)切換功能
存在腦裂
6橘忱、Redis Cluster
Redis Cluster
From: http://intro2libsys.com/focused-redis-topics/day-one/intro-redis-cluster
Redis 3.0.0 在 2015 年 4 月 2 日正式發(fā)布赴魁,距今已有兩年多的時(shí)間。Redis 集群采用 P2P 模式钝诚,無(wú)中心化颖御。把 key 分成 16384 個(gè) slot,每個(gè)實(shí)例負(fù)責(zé)一部分 slot凝颇∨斯埃客戶(hù)端請(qǐng)求對(duì)應(yīng)的數(shù)據(jù),若該實(shí)例 slot 沒(méi)有對(duì)應(yīng)的數(shù)據(jù)拧略,該實(shí)例會(huì)轉(zhuǎn)發(fā)給對(duì)應(yīng)的實(shí)例芦岂。另外,Redis 集群通過(guò) Gossip 協(xié)議同步節(jié)點(diǎn)信息垫蛆。
優(yōu)點(diǎn):
組件 all-in-box禽最,部署簡(jiǎn)單腺怯,節(jié)約機(jī)器資源
性能比 proxy 模式好
自動(dòng)故障轉(zhuǎn)移、Slot 遷移中數(shù)據(jù)可用
官方原生集群方案川无,更新與支持有保障
缺點(diǎn):
架構(gòu)比較新呛占,最佳實(shí)踐較少
多鍵操作支持有限(驅(qū)動(dòng)可以曲線(xiàn)救國(guó))
為了性能提升,客戶(hù)端需要緩存路由表信息
節(jié)點(diǎn)發(fā)現(xiàn)懦趋、reshard 操作不夠自動(dòng)化
7晾虑、Twemproxy
Twemproxy
From: http://engineering.bloomreach.com/the-evolution-of-fault-tolerant-redis-cluster
多個(gè)同構(gòu) Twemproxy(配置相同)同時(shí)工作,接受客戶(hù)端的請(qǐng)求愕够,根據(jù) hash 算法走贪,轉(zhuǎn)發(fā)給對(duì)應(yīng)的 Redis佛猛。
Twemproxy 方案比較成熟了惑芭,之前我們團(tuán)隊(duì)長(zhǎng)期使用此方案,但是效果并不是很理想继找。一方面是定位問(wèn)題比較困難遂跟,另一方面是它對(duì)自動(dòng)剔除節(jié)點(diǎn)的支持不是很友好。
優(yōu)點(diǎn):
開(kāi)發(fā)簡(jiǎn)單婴渡,對(duì)應(yīng)用幾乎透明
歷史悠久幻锁,方案成熟
缺點(diǎn):
代理影響性能
LVS 和 Twemproxy 會(huì)有節(jié)點(diǎn)性能瓶頸
Redis 擴(kuò)容非常麻煩
Twitter 內(nèi)部已放棄使用該方案,新使用的架構(gòu)未開(kāi)源
8边臼、Codis
Codis
From: https://github.com/CodisLabs/codis
Codis 是由豌豆莢開(kāi)源的產(chǎn)品哄尔,涉及組件眾多,其中 ZooKeeper 存放路由表和代理節(jié)點(diǎn)元數(shù)據(jù)柠并、分發(fā) Codis-Config 的命令岭接;Codis-Config 是集成管理工具,有 Web 界面供使用臼予;Codis-Proxy 是一個(gè)兼容 Redis 協(xié)議的無(wú)狀態(tài)代理鸣戴;Codis-Redis 基于 Redis 2.8 版本二次開(kāi)發(fā),加入 slot 支持粘拾,方便遷移數(shù)據(jù)窄锅。
優(yōu)點(diǎn):
開(kāi)發(fā)簡(jiǎn)單,對(duì)應(yīng)用幾乎透明
性能比 Twemproxy 好
有圖形化界面缰雇,擴(kuò)容容易入偷,運(yùn)維方便
缺點(diǎn):
代理依舊影響性能
組件過(guò)多,需要很多機(jī)器資源
修改了 Redis 代碼械哟,導(dǎo)致和官方無(wú)法同步疏之,新特性跟進(jìn)緩慢
開(kāi)發(fā)團(tuán)隊(duì)準(zhǔn)備主推基于 Redis 改造的 reborndb
四、最佳實(shí)踐
所謂的最佳實(shí)踐戒良,都是最適合具體場(chǎng)景的實(shí)踐体捏。
主推以下方案:
Redis Sentinel 集群 + 內(nèi)網(wǎng) DNS + 自定義腳本
Redis Sentinel 集群 + VIP + 自定義腳本
以下是實(shí)戰(zhàn)過(guò)程中總結(jié)出的最佳實(shí)踐:
Redis Sentinel 集群建議使用 >= 5 臺(tái)機(jī)器
不同的大業(yè)務(wù)可以使用一套 Redis Sentinel 集群,代理該業(yè)務(wù)下的所有端口
根據(jù)不同的業(yè)務(wù)劃分好 Redis 端口范圍
自定義腳本建議采用 Python 實(shí)現(xiàn),擴(kuò)展便利
自定義腳本需要注意判斷當(dāng)前的 Sentinel 角色
自定義腳本傳入?yún)?shù):
自定義腳本需要遠(yuǎn)程 ssh 操作機(jī)器几缭,建議使用 paramiko 庫(kù)河泳,避免重復(fù)建立 SSH 連接,消耗時(shí)間
加速 SSH 連接年栓,建議關(guān)閉以下兩個(gè)參數(shù)
UseDNS no
GSSAPIAuthentication no
微信或者郵件告警拆挥,建議 fork 一個(gè)進(jìn)程,避免主進(jìn)程阻塞
自動(dòng)切換和故障切換某抓,所有操作建議在 15s 以?xún)?nèi)完成
喜歡小編就輕輕關(guān)注一下吧纸兔!