得物 Redis 設(shè)計(jì)與實(shí)踐
一、前言
自建 Redis 系統(tǒng)是得物 DBA 團(tuán)隊(duì)自研高性能分布式 KV 緩存系統(tǒng),目前管理的 ECS 內(nèi)存總?cè)萘砍^數(shù)十TB,數(shù)百多個(gè) Redis 緩存集群實(shí)例,數(shù)萬多個(gè) Redis 數(shù)據(jù)節(jié)點(diǎn),其中內(nèi)存規(guī)格超過 1T 的大容量集群多個(gè)。
自建 Redis 系統(tǒng)采用 Proxy 架構(gòu),包含 ConfigServer、Proxy 等核心組件,還包括一個(gè)具備實(shí)例自動(dòng)化部署、資源管理、診斷與分析等重要功能在內(nèi)的完善的自動(dòng)化運(yùn)維平臺(tái)。
本文將從系統(tǒng)架構(gòu)及核心組件、自建 Redis 支持的重要特性、自動(dòng)化運(yùn)維平臺(tái)的重要功能等多方面為大家介紹自建 Redis 系統(tǒng)。
二、自建 Redis 架構(gòu)及核心組件
自建 Redis 分布式 KV 緩存系統(tǒng)由 ConfigServer、Redis-Proxy、Redis-Server 等核心組件構(gòu)成,整體架構(gòu)圖如下所示:
圖片
下面為大家逐一介紹自建 Redis 各核心組件支持的重要功能和特性。
ConfigServer
ConfigServer 是自建 Redis 系統(tǒng)中關(guān)鍵組件之一,跨多可用區(qū)多節(jié)點(diǎn)部署,采用 Raft 協(xié)議實(shí)現(xiàn) ConfigServer 組件高可用;ConfigServer 主要負(fù)責(zé)三方面職責(zé):
負(fù)責(zé) Proxy 添加與刪除、Group 創(chuàng)建與刪除、Redis-Server 實(shí)例添加與刪除、Redis-Server 實(shí)例手動(dòng)主從切換、水平擴(kuò)容與數(shù)據(jù)遷移等功能操作。
集群拓?fù)浒l(fā)生變化時(shí),主動(dòng)向 Redi-Proxy 更新集群拓?fù)洹?/p>
負(fù)責(zé) Redis-Server 實(shí)例故障檢測與自動(dòng)故障轉(zhuǎn)移(主節(jié)點(diǎn)故障后自動(dòng)主從切換)。
ConfigServer 系統(tǒng)結(jié)構(gòu)圖如下所示:
圖片
每個(gè)自建 Redis 集群會(huì)對應(yīng)部署一組獨(dú)立的 ConfigServer 組件,并且每組 ConfigServer 采用至少三節(jié)點(diǎn)部署,分布在三個(gè)不同的可用區(qū),保證自建 Redis 系統(tǒng)高可用:
- ConfigServer 多節(jié)點(diǎn)多可用區(qū)部署,保證了 ConfigServer 組件自身的高可用。
- 同時(shí),也保證 Redis-Server 的高可用,任意一個(gè)可用區(qū)故障,剩余 ConfigServer 依然能高效完成 Redis-Server 的宕機(jī)判定、選主與故障 Failover。
- 相對于開源 Redis 原生 Cluster 模式,也不會(huì)因多數(shù) Redis-Server 主節(jié)點(diǎn)故障而無法完成故障判定與 Failover。
故障檢測與轉(zhuǎn)移
ConfigServer 負(fù)責(zé) Redis-Server 節(jié)點(diǎn)故障檢測與自動(dòng)故障轉(zhuǎn)移,ConfigServer 會(huì)對每一個(gè) Group 的 Master 節(jié)點(diǎn)進(jìn)行定期探活,如果發(fā)現(xiàn)某一個(gè) Group 的 Master 節(jié)點(diǎn)不可用,就會(huì)執(zhí)行 Failover 流程,選擇該 Group 內(nèi)一個(gè)可用的 Slave 節(jié)點(diǎn)提升為新的 Master 節(jié)點(diǎn),保證該 Group 可繼續(xù)對外提供服務(wù)。
實(shí)現(xiàn)思路參考開源 Redis Sentinel,不過由于 ConfigServer 是 Golang 實(shí)現(xiàn),而開源 Redis Sentinel 是使用 C 語言實(shí)現(xiàn),所以在部分細(xì)節(jié)上略有不同。
多協(xié)程:在 Redis Sentinel 中,是在一個(gè)單線程中定時(shí)檢測所有 Redis-Server 節(jié)點(diǎn),而由于 Golang 支持協(xié)程,在 ConfigServer 中是為實(shí)例的每個(gè) Group 開啟一個(gè)協(xié)程,在協(xié)程中定時(shí)檢測該 Group 對應(yīng)的 Redis-Server 狀態(tài)。
自定義通訊協(xié)議:在 Redis Sentinel 中,Sentinel 之間通過 Redis-Server 節(jié)點(diǎn)交換元數(shù)據(jù)信息,來發(fā)現(xiàn)負(fù)責(zé)同一個(gè) Redis-Server 的 Sentinel 節(jié)點(diǎn),以及交換觀察的節(jié)點(diǎn)狀態(tài);而在 ConfigServer 中,ConfigServer 之間是采用自定義 TCP 協(xié)議直接通訊,交換信息更高效,也能縮短故障切換時(shí)間。
故障檢測
- 每個(gè) ConfigServer 定期給該實(shí)例的所有 Redis-Server 節(jié)點(diǎn)發(fā)送 Ping 和 Info 命令,用于檢測節(jié)點(diǎn)的可用性和發(fā)現(xiàn)新的從節(jié)點(diǎn)。
- 當(dāng) ConfigServer 向 Redis-Server 節(jié)點(diǎn)發(fā)送命令超時(shí)時(shí),將節(jié)點(diǎn)標(biāo)記為主觀下線,并傳播節(jié)點(diǎn)的主觀下線狀態(tài)。
- ConfigServer Leader 節(jié)點(diǎn)發(fā)現(xiàn)某節(jié)點(diǎn)處于主觀下線時(shí),會(huì)主動(dòng)查詢其他 ConfigServer 對該節(jié)點(diǎn)的狀態(tài)判定,如果多數(shù) ConfigServer 節(jié)點(diǎn)都將該 Redis-Server 節(jié)點(diǎn)標(biāo)記為主觀下線,則 Leader 節(jié)點(diǎn)將該 Redis 節(jié)點(diǎn)標(biāo)記為客觀下線,并發(fā)起故障轉(zhuǎn)移流程。
故障轉(zhuǎn)移
- 從故障 Redis 主節(jié)點(diǎn)的所有從節(jié)點(diǎn)中選擇一個(gè)最優(yōu)的從節(jié)點(diǎn),選擇策略包含:
過濾掉不健康的從節(jié)點(diǎn),比如處于主觀下線或者客觀下線狀態(tài)。
選擇 Slave-Priority 最高的從節(jié)點(diǎn)。
選擇復(fù)制偏移量最大的從節(jié)點(diǎn)。
選擇 Runid 最小的從節(jié)點(diǎn)。
- 將選取出來的從節(jié)點(diǎn)提升為新的主節(jié)點(diǎn),即向該節(jié)點(diǎn)執(zhí)行 slaveof no one 命令。
- 將其他從節(jié)點(diǎn)設(shè)置為新主節(jié)點(diǎn)的從節(jié)點(diǎn)。
- 并保持對舊主節(jié)點(diǎn)的狀態(tài)關(guān)注,如果舊主節(jié)點(diǎn)恢復(fù),將舊主節(jié)點(diǎn)也更新為新主節(jié)點(diǎn)的從節(jié)點(diǎn)。
Redis-Proxy
Redis-Proxy 組件是自建 Redis 系統(tǒng)中的代理服務(wù),負(fù)責(zé)接受客戶端連接,然后轉(zhuǎn)發(fā)客戶端命令到后端相應(yīng)的 Redis-Server 節(jié)點(diǎn),使得后端 Redis-Server 集群部署架構(gòu)對業(yè)務(wù)透明,Proxy 支持 Redis RESP 協(xié)議,業(yè)務(wù)訪問 Proxy 就像訪問一個(gè)單點(diǎn) Redis 服務(wù)一樣,業(yè)務(wù)可以把一個(gè)自建 Redis 集群當(dāng)作一個(gè)容量無限大的單點(diǎn) Redis 實(shí)例即可。
自建 Redis 為每個(gè)實(shí)例部署一組獨(dú)立的 Proxy 節(jié)點(diǎn),Proxy 是一個(gè)無狀態(tài)服務(wù),可以很方便的進(jìn)行水平擴(kuò)容,提高業(yè)務(wù)訪問自建 Redis 系統(tǒng)的 QPS。
在自建 Redis 中,每個(gè)集群可能包含多個(gè) Group,每個(gè) Group 對應(yīng)一組主從 Redis-Server 節(jié)點(diǎn),每個(gè) Group 負(fù)責(zé)一部分 Key,同時(shí),整個(gè)集群劃分為 1024 個(gè)槽(slot),每個(gè) Group 負(fù)責(zé)其中一部分槽(slot),用戶寫入的 Key 通過以下算法來計(jì)算對應(yīng)的 slot,然后存儲(chǔ)到對應(yīng)節(jié)點(diǎn)。
slot 計(jì)算公式: slot(key) = crc32(key) % 1024
圖片
Proxy 接收到用戶命令后,提取訪問的 Key,通過上面同樣算法計(jì)算相應(yīng)的 slot,獲取負(fù)責(zé)該 slot 的對應(yīng) Redis-Server 實(shí)例的連接,再將用戶命令轉(zhuǎn)發(fā)到對應(yīng)的 Redis-Server 實(shí)例上執(zhí)行,讀取 Redis-Server 返回的結(jié)果發(fā)送給用戶。
DBA 團(tuán)隊(duì)針對 Proxy 組件做了大量性能優(yōu)化,相比市面上開源的支持 Redis RESP 協(xié)議的 Proxy 版本,臨時(shí)對象內(nèi)存分配減少了約 20 倍,極大的減輕 GC 壓力以及 GC 消耗的 CPU;大量短鏈接場景下,QPS 提升約10%。
同時(shí),自建 Redis-Proxy 還支持同城雙活、異步雙寫等特色功能。
同城雙活
自建 Redis 為了保證數(shù)據(jù)的高可用和高可靠,每個(gè) Redis 實(shí)例中每個(gè)分組采用至少一主一從的部署方案,且主從節(jié)點(diǎn)分別部署在不同可用區(qū),在默認(rèn)的訪問模式下,業(yè)務(wù)讀寫都訪問主節(jié)點(diǎn),從節(jié)點(diǎn)僅僅作為熱備節(jié)點(diǎn)。
為了提升業(yè)務(wù)在多可用區(qū)部署場景下訪問緩存性能與降低延遲,以及最大化利用從節(jié)點(diǎn)的價(jià)值,自建 Redis-Proxy 支持同城雙活功能。自建 Redis 同城雙活采用單寫就近讀的方案實(shí)現(xiàn),實(shí)現(xiàn)原理圖如下所示:
圖片
注:需要通過以下方式之一來實(shí)現(xiàn)動(dòng)態(tài)配置
- 通過容器的 ServiceName 實(shí)現(xiàn)同 AZ Proxy 節(jié)點(diǎn)優(yōu)先訪問 (優(yōu)先)。
- 通過云廠商的 PrivateZone 實(shí)現(xiàn)智能 DNS 解析(容器和非容器應(yīng)用都行)。
Redis-Server
- 采用至少一主一從的部署方案,并且主從節(jié)點(diǎn)跨可用區(qū)部署,分別部署在與業(yè)務(wù)對應(yīng)的可用區(qū)。
Redis-Proxy
- Redis-Proxy 同樣采用多可用區(qū)部署,與業(yè)務(wù)可用區(qū)相同。
- 各可用區(qū) Proxy 將寫請求自動(dòng)路由到主節(jié)點(diǎn),依然寫主節(jié)點(diǎn)。
- 讀請求優(yōu)先就近訪問本可用區(qū)從節(jié)點(diǎn),本可用區(qū)無可用從節(jié)點(diǎn)時(shí),支持自動(dòng)訪問主節(jié)點(diǎn)或優(yōu)先訪問其他可用區(qū)從節(jié)點(diǎn)。
異步雙寫
針對業(yè)務(wù)從云 Redis 遷移到自建 Redis、以及大集群拆分場景,對于數(shù)據(jù)可靠性要求高的業(yè)務(wù),Proxy 支持雙寫功能。
以從云 Redis 遷移到自建 Redis 為例,遷移期間 Proxy 同時(shí)寫云 Redis 和自建 Redis,保證兩邊數(shù)據(jù)實(shí)時(shí)一致,從而可以隨時(shí)回滾,做到平滑遷移。
Proxy 雙寫功能具備以下特性:
- Proxy 雙寫功能采用異步雙寫操作實(shí)現(xiàn),性能優(yōu)異,雙寫操作對業(yè)務(wù)幾乎無影響。
- Proxy 支持轉(zhuǎn)發(fā)、只讀、雙寫等多種模式,業(yè)務(wù)接入自建 Redis 后,自建 Redis 通過在線動(dòng)態(tài)更改配置,平滑的完成整個(gè)切換過程,無需業(yè)務(wù)頻繁更改配置或者重啟等。
- Proxy 雙寫支持云 Redis 優(yōu)先或者自建 Redis 優(yōu)先(以云 Redis 遷移為例),且可在線動(dòng)態(tài)調(diào)整。
- 同時(shí),提供數(shù)據(jù)比對工具,用于雙寫期間數(shù)據(jù)對比,隨時(shí)觀察兩邊數(shù)據(jù)一致性情況;數(shù)據(jù)對比支持多種策略,包括對比類型、對比長度或元素?cái)?shù)量。
Redis-Server
Redis-Server 組件為開源 Redis 版本基礎(chǔ)上,增加槽 slot 同步遷移與異步遷移等相關(guān)功能;支持原生開源 Redis 的所有特性,比如支持 String、Hash、List、Set、ZSet 等常用數(shù)據(jù)結(jié)構(gòu),AOF 持久化、主從復(fù)制、Lua腳本等等。
Share-Nothing 架構(gòu):自建 Redis 系統(tǒng)中,Redis-Server 服務(wù)采用集群化部署,整個(gè)集群由多個(gè) Group 共同組成,每個(gè) Group 中包含一主 N 從多個(gè) Redis-Server 實(shí)例,Group 之間的 Redis-Server 節(jié)點(diǎn)相互沒有通信,為 Share-Nothing 架構(gòu)。同時(shí),整個(gè)集群劃分為 1024 個(gè)槽(slot),每個(gè) Group 負(fù)責(zé)其中一部分槽(slot),用戶寫入的 Key 通過上面提到的算法來計(jì)算對應(yīng)的 slot,然后存儲(chǔ)到負(fù)責(zé)該 slot 的 Group 中的 Redis-Server 節(jié)點(diǎn)上。查詢 Key 時(shí),通過同樣的算法去對應(yīng)的節(jié)點(diǎn)上查詢。
Async-Fork 特性
在 Redis 中,在 AOF 文件重寫、生成 RDB 備份文件以及主從全量同步過程中,都需要使用系統(tǒng)調(diào)用 Fork 創(chuàng)建一個(gè)子進(jìn)程來獲取內(nèi)存數(shù)據(jù)快照,在 Fork() 函數(shù)創(chuàng)建子進(jìn)程的時(shí)候,內(nèi)核會(huì)把父進(jìn)程的「頁表」復(fù)制一份給子進(jìn)程,如果頁表很大,在現(xiàn)有常見操作系統(tǒng)中,復(fù)制頁表的過程耗時(shí)會(huì)非常長,那么在此期間,業(yè)務(wù)訪問 Redis 讀寫延遲會(huì)大幅增加。
自建 Redis 系統(tǒng)中,Redis-Server 通過優(yōu)化并適配最新的支持 Async-Fork 特性的操作系統(tǒng),極大的提升 Fork 操作性能:
- Fork 命令耗時(shí)大幅減小,并且不隨數(shù)據(jù)量增長而增長,基本穩(wěn)定在 200 微秒左右;
- TP100 抖動(dòng)得到明顯改善,TP100 值也不隨數(shù)據(jù)量增長而變大,基本在 1-2 毫秒左右;
- 相比原生 Redis Fork 耗時(shí)減少 98%。日常運(yùn)維中,添加從節(jié)點(diǎn)、主從切換、RDB 離線分析等常見運(yùn)維操作均對業(yè)務(wù)無感知,不會(huì)造成業(yè)務(wù)性能抖動(dòng)。
圖片
圖片
注:該圖表使用了雙縱坐標(biāo)詳細(xì)內(nèi)容可閱讀《VLDB 頂會(huì)論文 Async-fork 解讀與 Redis 實(shí)踐》。
數(shù)據(jù)遷移
為什么需要做數(shù)據(jù)遷移?主要是為了水平擴(kuò)容,自建 Redis 將每個(gè)集群實(shí)例劃分為固定數(shù)量的槽 slot,每個(gè) Group 負(fù)責(zé)一部分槽,當(dāng)進(jìn)行水平擴(kuò)容時(shí),需要重新分配 slot 的分布,并且將一部分 slot 從原有節(jié)點(diǎn)遷移到新節(jié)點(diǎn),同時(shí)將由 slot 負(fù)責(zé)的數(shù)據(jù)一起遷移到新節(jié)點(diǎn)。
數(shù)據(jù)遷移過程包括在源節(jié)點(diǎn)將 Key 對應(yīng)的 Value 使用 Dump 命令進(jìn)行序列化,然后將數(shù)據(jù)發(fā)送到目標(biāo)節(jié)點(diǎn),目標(biāo)節(jié)點(diǎn)使用 Restore 命令將 Key 和 Value 存儲(chǔ)到本地 Redis 中,最后源節(jié)點(diǎn)將該 Key 刪除。
自建 Redis 支持同步遷移與異步遷移兩種方式。
圖片
圖片
同步遷移:即在上述整個(gè)遷移過程中,源端的 Migrate 命令處于阻塞狀態(tài),直到目標(biāo)端成功加載數(shù)據(jù),并且返回成功,源節(jié)點(diǎn)刪除該 Key 后,Migrate 命令才響應(yīng)客戶端成功。由于 Redis 數(shù)據(jù)操作是一個(gè)單線程模型,所有命令的處理的都在主線程中處理,因此 Migrate 命令會(huì)極大地影響其他正常業(yè)務(wù)的訪問。
異步遷移:Migrate 命令僅阻塞 Dump 序列化數(shù)據(jù)、并且異步發(fā)送到目標(biāo)節(jié)點(diǎn),然后即返回客戶端成功;目標(biāo)節(jié)點(diǎn)接收到數(shù)據(jù)后,使用 Restore 命令進(jìn)行保存,保存成功后,主動(dòng)給源節(jié)點(diǎn)發(fā)送一個(gè) ACK 命令,通知源節(jié)點(diǎn)將遷移的 Key 刪除。異步遷移減少源端 Migrate 命令的阻塞時(shí)間,減少了 slot 遷移過程中對業(yè)務(wù)的影響。
三、自動(dòng)化運(yùn)維平臺(tái)
自建 Redis 系統(tǒng)擁有功能完善的自動(dòng)化運(yùn)維平臺(tái)。其主要功能包括:緩存實(shí)例自動(dòng)化部署、快速水平擴(kuò)容與垂直擴(kuò)容、多維度資源管理、診斷與分析等。
運(yùn)維平臺(tái)架構(gòu)
自建 Redis 自動(dòng)化運(yùn)維平臺(tái)包括Redis 管控平臺(tái)、Kv-Admin、Kv-Agent、Prometheus 等組件,部署架構(gòu)如下圖所示:
圖片
Redis 管控平臺(tái)
Redis 管控平臺(tái)是自建 Redis 綜合運(yùn)維管理平臺(tái),自建 Redis 的可視化操作均在 Redis 管控平臺(tái)上完成,包括實(shí)例部署、擴(kuò)容、數(shù)據(jù)遷移等在內(nèi)的所有日常運(yùn)維操作均可在管理平臺(tái)上完成。
Kv-Admin
Kv-Admin 是自動(dòng)化運(yùn)維平臺(tái)的核心組件,負(fù)責(zé)處理所有前端發(fā)送過來的請求,核心功能包括:
- 負(fù)責(zé)完成實(shí)例部署時(shí)任務(wù)調(diào)度、機(jī)器推薦、端口分配、SLB 推薦與綁定。
- 實(shí)例列表展示、實(shí)例基本信息查詢。
- 數(shù)據(jù)離線分析與保存。
- 資源池管理及生成資源報(bào)表。
Kv-Agent
每個(gè) ECS 上會(huì)部署一個(gè) Kv-Agent 組件,Kv-Agent 負(fù)責(zé)完成實(shí)例部署、實(shí)例啟停等操作;基于心跳元數(shù)據(jù)的 Exporter 自動(dòng)注冊與解除;
同時(shí),Kv-Agent 包含 Exporter 模塊,負(fù)責(zé) Redis-Server 節(jié)點(diǎn)的監(jiān)控信息采集,然后將數(shù)據(jù)規(guī)范化后通過端點(diǎn)暴露給 Prometheus。
APM / Prometheus
APM 監(jiān)控平臺(tái)或者 Prometheus 負(fù)責(zé)從 Exporter 暴露的端點(diǎn)拉取監(jiān)控?cái)?shù)據(jù);自建 Redis 監(jiān)控與告警均接入公司 APM 平臺(tái)。
實(shí)例自動(dòng)化部署
一個(gè)緩存實(shí)例的部署非常復(fù)雜,涉及機(jī)器選擇、配置文件準(zhǔn)備、節(jié)點(diǎn)安裝與啟動(dòng)、槽位分配、主從關(guān)系設(shè)置、SLB 分配與綁定、以及相關(guān)組件的部署等一系列動(dòng)作。
自動(dòng)化運(yùn)維平臺(tái)支持安裝包版本管理,在部署頁面選擇合適的包版本、配置對應(yīng)實(shí)例可用區(qū)、規(guī)格等基本信息后,一鍵操作即可完成 ConfigServer、Redis-Proxy、Redis-Server 等組件的部署,自動(dòng)完成組件部署過程中涉及的上述機(jī)器推薦、配置文件準(zhǔn)備、節(jié)點(diǎn)安裝與啟動(dòng)等所有過程。

為了保證實(shí)例中所有組件的高可用,自動(dòng)化部署過程中包含一些必要的部署規(guī)則:
- ConfigServer 組件會(huì)部署在三個(gè)不同的可用區(qū)。
- 避免同一個(gè)集群實(shí)例的多個(gè) Redis-Server、Redis-Proxy 節(jié)點(diǎn)部署在相同的 ECS 上,每個(gè) ECS 上可部署的同一個(gè)集群實(shí)例的 Server 或 Proxy 組件數(shù)量可配置。
- 每個(gè) ECS 最多分配總內(nèi)存容量的 90%,預(yù)留一定的數(shù)據(jù)增長空間。
- 根據(jù) ECS 可用內(nèi)存,優(yōu)先推薦剩余可用內(nèi)存多的 ECS。
- 根據(jù) Group 數(shù)量,自動(dòng)均衡分配每個(gè) Group 負(fù)責(zé)的 slot 數(shù)量。
- 根據(jù) SLB 近三天的流量峰值,自動(dòng)綁定最優(yōu)的 SLB。
實(shí)例擴(kuò)容
當(dāng)業(yè)務(wù)數(shù)據(jù)增長導(dǎo)致實(shí)例內(nèi)存使用率超過一定閾值后,根據(jù)單節(jié)點(diǎn)分配的最大內(nèi)存、實(shí)例的 Group 數(shù)量等情況綜合考慮,運(yùn)維可選擇為實(shí)例進(jìn)行垂直擴(kuò)容或者水平擴(kuò)容。
垂直擴(kuò)容,即動(dòng)態(tài)修改單節(jié)點(diǎn)的 Maxmemory 參數(shù),提高單節(jié)點(diǎn)的容量。
水平擴(kuò)容,即增加實(shí)例的 Group 數(shù)量,對應(yīng)增加主從節(jié)點(diǎn)數(shù)量,然后重新進(jìn)行 slot 分配和對應(yīng)的數(shù)據(jù)遷移動(dòng)作。
一般來說,當(dāng)單節(jié)點(diǎn)規(guī)格小于 4G 時(shí),會(huì)優(yōu)先考慮垂直擴(kuò)容,簡單快速,對業(yè)務(wù)無任何影響。
自動(dòng)化運(yùn)維平臺(tái)支持方便的垂直擴(kuò)容和水平擴(kuò)容操作。
對于垂直擴(kuò)容,運(yùn)維平臺(tái)支持批量調(diào)整實(shí)例 Redis-Server 節(jié)點(diǎn)的容量。
對于水平擴(kuò)容,同實(shí)例初始部署一樣,運(yùn)維平臺(tái)支持新增 Redis-Server 節(jié)點(diǎn)的自動(dòng)化部署、主從關(guān)系設(shè)置等,同時(shí)支持按照實(shí)例總節(jié)點(diǎn)數(shù)重新自動(dòng)均衡分配每個(gè) Group 負(fù)責(zé)的 slot 數(shù)量,并自動(dòng)完成數(shù)據(jù)遷移,數(shù)據(jù)遷移進(jìn)度可視化。
資源管理
自建 Redis 運(yùn)維平臺(tái)目前管理的 ECS 超過數(shù)千臺(tái),運(yùn)維平臺(tái)支持 ECS 資源批量添加、資源分配、資源鎖定、資源推薦等資源管理功能,以及提供資源利用率報(bào)表。
運(yùn)維平臺(tái)支持 ECS 可用內(nèi)存的管理與分配,運(yùn)維平臺(tái)記錄每臺(tái) ECS 的剩余可分配內(nèi)存容量,Redis-Server 實(shí)例部署時(shí),優(yōu)先推薦剩余可分配內(nèi)存多的 ECS,分配出去的 ECS 更新對應(yīng)的可用內(nèi)存容量。
Redis-Proxy 和 ConfigServer 部署時(shí),優(yōu)先推薦部署的實(shí)例數(shù)量較少的 ECS。
診斷與分析
計(jì)算實(shí)例綜合得分:運(yùn)維平臺(tái)通過分析所有實(shí)例關(guān)鍵監(jiān)控指標(biāo)前一天的峰值,再根據(jù)各項(xiàng)指標(biāo)的權(quán)重,每天自動(dòng)計(jì)算所有實(shí)例的得分,根據(jù)各實(shí)例的得分即可快速了解各實(shí)例的使用健康度。
參與計(jì)算得分的關(guān)鍵指標(biāo)包括:Proxy CPU、Redis CPU、Redis 內(nèi)存使用率、Proxy 占用內(nèi)存、Proxy GC 次數(shù)、最大 RT、Redis 流入流量、Redis 流出流量等。
慢日志:運(yùn)維平臺(tái)支持 Redis-Server 記錄的慢日志和 Redis-proxy 記錄的慢日志查詢。
RDB 離線分析:運(yùn)維平臺(tái)支持生成 RDB 文件,并自動(dòng)進(jìn)行數(shù)據(jù)離線分析。分析結(jié)果包含 Top100 Value 最大的 Key 和元素個(gè)數(shù)最多的 Key;每種類型 Key,不同 Key 前綴包含的 Key 數(shù)量等。
圖片
四、監(jiān)控與告警
自建 Redis 系統(tǒng)接入 APM 監(jiān)控平臺(tái),提供了各種維度的監(jiān)控指標(biāo)和告警功能,及時(shí)對異常情況進(jìn)行預(yù)警,當(dāng)出現(xiàn)問題時(shí),也能幫助快速定位問題。
監(jiān)控
ECS:CPU、系統(tǒng) Load、內(nèi)存、網(wǎng)絡(luò)流量、網(wǎng)絡(luò)丟包、磁盤 IO 等。
Proxy:QPS、TP999/TP9999/TP100、連接數(shù)、CPU、 內(nèi)存、GC、Goroutine 數(shù)量等。
Server:CPU、內(nèi)存、網(wǎng)絡(luò)、連接數(shù)、QPS、Key 數(shù)量、命中率、訪問 RT等。
告警
自建 Redis 包含大量的告警指標(biāo):
- ECS CPU 使用率、內(nèi)存使用率、系統(tǒng) Load(5 分鐘平均值)、流量。
- SLB 流量。
- Server、Proxy、ConfigServer 節(jié)點(diǎn)宕機(jī)。
- 主節(jié)點(diǎn)缺失從節(jié)點(diǎn)、主節(jié)點(diǎn)可用區(qū)不一致、主從角色切換。
五、穩(wěn)定性治理
資源隔離
自建 Redis 目前所有組件都是部署在 ECS 上,為了提高資源利用率節(jié)約成本,大部分業(yè)務(wù)域的 Redis 集群都是混布的。自建 Redis 運(yùn)維平臺(tái)目前管理 ECS 超過數(shù)千臺(tái),接入的業(yè)務(wù)也涵蓋營銷、風(fēng)控、算法、投放、社區(qū)、大數(shù)據(jù)等等,每個(gè)業(yè)務(wù)的實(shí)例等級(jí)、QPS、流量等指標(biāo)各有差異,少數(shù)業(yè)務(wù) Redis 可能存在突發(fā)寫入流量高、Proxy CPU毛刺等現(xiàn)象,可能會(huì)引起相同 ECS 上其他實(shí)例性能抖動(dòng)。
按標(biāo)簽分類:為了方便資源隔離與資源分配時(shí)管理,所有 ECS 資源按標(biāo)簽進(jìn)行分類管理,針對特殊需求業(yè)務(wù)、大流量實(shí)例、通用資源池等劃分不同的資源標(biāo)簽,實(shí)例部署時(shí)選擇合適的標(biāo)簽、或者頻繁出現(xiàn)告警時(shí)調(diào)整到對應(yīng)資源池進(jìn)行隔離,避免相互影響。
Proxy CPU 限制:為了防止單個(gè) Redis-Proxy 進(jìn)程搶占過多 CPU 資源,Redis-Proxy 支持配置 Golang GOMAXPROCS 參數(shù)來設(shè)置單個(gè)進(jìn)程允許使用的最大 CPU 核數(shù)。
巡檢
為了提前發(fā)現(xiàn)潛在的風(fēng)險(xiǎn),除了日常告警外,我們支持自動(dòng)巡檢工具和巡檢信息頁面,建立了定期巡檢機(jī)制。
實(shí)例綜合得分排名:運(yùn)維平臺(tái)通過分析所有實(shí)例關(guān)鍵監(jiān)控指標(biāo)前一天的峰值,再根據(jù)各項(xiàng)指標(biāo)的權(quán)重,每天自動(dòng)計(jì)算所有實(shí)例的得分,在巡檢信息頁面進(jìn)行展示,通過得分排序即可快速發(fā)現(xiàn)風(fēng)險(xiǎn)實(shí)例。
圖片
ECS 資源大盤:實(shí)時(shí)展示所有 Redis-Proxy 和 Redis-Server 使用 ECS 的重要指標(biāo),通過排序即可快速瀏覽各 ECS 各項(xiàng)重要指標(biāo),如 CPU 使用率、內(nèi)存使用率、IOPS 使用率、磁盤讀取/寫入、上傳/下載帶寬等。
自動(dòng)巡檢工具:定期檢查所有實(shí)例的配置、節(jié)點(diǎn)數(shù)量等基本信息,對于如從節(jié)點(diǎn)缺失、可用區(qū)不一致、節(jié)點(diǎn)配置不一致等異常情況進(jìn)行提示。
故障演練
為了提高自建 Redis 系統(tǒng)在異常場景下的可用性、檢驗(yàn)自建 Redis 系統(tǒng)在各異常場景的恢復(fù)時(shí)間,我們不定期進(jìn)行多次故障演練。
故障演練涵蓋所有組件在ECS、網(wǎng)絡(luò)、磁盤等出現(xiàn)故障的場景,以及多個(gè)組件組合同時(shí)出現(xiàn)這些故障的場景。
經(jīng)過故障演練檢驗(yàn),自建 Redis 系統(tǒng) Redis-Server 主節(jié)點(diǎn)故障恢復(fù)時(shí)間 12s,Redis-Proxy 故障業(yè)務(wù)恢復(fù)時(shí)間 5s 內(nèi)。
六、總結(jié)
本文詳細(xì)介紹了自建 Redis 架構(gòu)和現(xiàn)有一些重要特性,我們還在持續(xù)不斷地迭代優(yōu)化和豐富支持的特性,為我們的業(yè)務(wù)提供一個(gè)功能更強(qiáng)大、性能更優(yōu)異的分布式緩存系統(tǒng)。未來我們還會(huì)迭代的方向可能包括且不限于:
- 目前 Redis-Server 為了兼容云上版本和分布式架構(gòu)做了很多定制化,所以未使用最新社區(qū)版本,未來會(huì)升級(jí)到最新的社區(qū)版本如 7.0。
- 熱 Key 訪問一直是 Redis 使用中對業(yè)務(wù)影響較大的一個(gè)問題,未來我們考慮支持熱 Key 統(tǒng)計(jì)與讀熱 Key 本地緩存。
- Golang 版本 Proxy 在高 QPS 請求時(shí),GC 是性能提升的一個(gè)瓶頸,未來考慮使用 Rust 重構(gòu) Proxy。





































