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