Redis 高可用架構最佳實踐
0×01 前言
2017 年 5 月 13 日,應用效能管理大講堂廣州站圓滿落幕,其中來自三七互娛的 DBA 溫國兵在會場與各位進行了精彩的 Redis 技術分享。
Redis 是一個開源的使用 ANSI C 語言編寫、支援網路、可基於記憶體亦可持久化的日誌型、Key-Value 資料庫,並提供多種語言的 API。
如今,網際網路業務的資料正以更快的速度在增長,資料型別越來越豐富,這對資料處理的速度和能力提出了更高要求。Redis 是一種開源的記憶體非關係型資料庫,給開發人員帶來的體驗是顛覆性的。在自始至終的設計過程中,都充分考慮高效能,這使得 Redis 成為當今速度最快的 NoSQL 資料庫。
考慮高效能的同時,高可用也是很重要的考慮因素。網際網路 7×24 無間斷服務,在故障期間以最快的速度 Failover,能給企業帶來最小的損失。
那麼,在實際應用中,都有哪些高可用架構呢?架構之間有何優劣?我們應該怎麼取捨?有哪些最佳實踐?
0×02 Sentinel 原理
在講解 Redis 高可用方案之前,我們先來看看 Redis Sentinel 原理是怎麼樣的。
- Sentinel 叢集通過給定的配置檔案發現 master,啟動時會監控 master。通過向 master 傳送 info 資訊獲得該伺服器下面的所有從伺服器。
- Sentinel 叢集通過命令連線向被監視的主從伺服器傳送 hello 資訊 (每秒一次),該資訊包括 Sentinel 本身的 IP、埠、id 等內容,以此來向其他 Sentinel 宣告自己的存在。
- Sentinel 叢集通過訂閱連線接收其他 Sentinel 傳送的 hello 資訊,以此來發現監視同一個主伺服器的其他 Sentinel;叢集之間會互相建立命令連線用於通訊,因為已經有主從伺服器作為傳送和接收 hello 資訊的中介,Sentinel 之間不會建立訂閱連線。
- Sentinel 叢集使用 ping 命令來檢測例項的狀態,如果在指定的時間內(down-after-milliseconds)沒有回覆或則返回錯誤的回覆,那麼該例項被判為下線。
- 當 failover 主備切換被觸發後,failover 並不會馬上進行,還需要 Sentinel 中的大多數 Sentinel 授權後才可以進行 failover,即進行 failover 的 Sentinel 會去獲得指定 quorum 個的 Sentinel 的授權,成功後進入 ODOWN 狀態。如在 5 個 Sentinel 中配置了 2 個 quorum,等到 2 個 Sentinel 認為 master 死了就執行 failover。
- Sentinel 向選為 master 的 slave 傳送 SLAVEOF NO ONE 命令,選擇 slave 的條件是 Sentinel 首先會根據 slaves 的優先順序來進行排序,優先順序越小排名越靠前。如果優先順序相同,則檢視複製的下標,哪個從 master 接收的複製資料多,哪個就靠前。如果優先順序和下標都相同,就選擇程式 ID 較小的。
- Sentinel 被授權後,它將會獲得宕掉的 master 的一份最新配置版本號 (config-epoch),當 failover 執行結束以後,這個版本號將會被用於最新的配置,通過廣播形式通知其它 Sentinel,其它的 Sentinel 則更新對應 master 的配置。
1 到 3 是自動發現機制:
- 以 10 秒一次的頻率,向被監視的 master 傳送 info 命令,根據回覆獲取 master 當前資訊。
- 以 1 秒一次的頻率,向所有 redis 伺服器、包含 Sentinel 在內傳送 PING 命令,通過回覆判斷伺服器是否線上。
- 以 2 秒一次的頻率,通過向所有被監視的 master,slave 伺服器傳送當前 Sentinel master 資訊的訊息。
4 是檢測機制,5 和 6 是 failover 機制,7 是更新配置機制。[1]
0×03 Redis 高可用架構
講解完 Redis Sentinel 原理之後,接下來講解常用的 Redis 高可用架構。
- Redis Sentinel 叢集 + 內網 DNS + 自定義指令碼
- Redis Sentinel 叢集 + VIP + 自定義指令碼
- 封裝客戶端直連 Redis Sentinel 埠
- JedisSentinelPool,適合 Java
- PHP 基於 phpredis 自行封裝
- Redis Sentinel 叢集 + Keepalived/Haproxy
- Redis M/S + Keepalived
- Redis Cluster
- Twemproxy
- Codis
接下來配合圖文逐個講解。
3.1 Redis Sentinel 叢集 + 內網 DNS + 自定義指令碼
上圖是已經線上上環境應用的方案。底層是 Redis Sentinel 叢集,代理著 Redis 主從,Web 端連線內網 DNS 提供服務。內網 DNS 按照一定的規則分配,比如 xxxx.redis.cache/queue.port.xxx.xxx
,第一個段表示業務簡寫,第二個段表示這是 Redis 內網域名,第三個段表示 Redis 型別,cache 表示快取,queue 表示佇列,第四個段表示 Redis 埠,第五、第六個段表示內網主域名。
當主節點發生故障,比如機器故障、Redis 節點故障或者網路不可達,Sentinel 叢集會呼叫 client-reconfig-script
配置的指令碼,修改對應埠的內網域名。對應埠的內網域名指向新的 Redis 主節點。
優點:
- 秒級切換,在 10s 內完成整個切換操作
- 指令碼自定義,架構可控
- 對應用透明,前端不用擔心後端發生什麼變化
缺點:
- 維護成本略高,Redis Sentinel 叢集建議投入 3 臺機器以上
- 依賴 DNS,存在解析延時
- Sentinel 模式存在短時間的服務不可用
- 服務通過外網訪問不可採用此方案
3.2 Redis Sentinel 叢集 + VIP + 自定義指令碼
此方案和上一個方案相比,略有不同。第一個方案使用了內網 DNS,第二個方案把內網 DNS 換成了虛擬 IP。底層是 Redis Sentinel 叢集,代理著 Redis 主從,Web 端通過 VIP 提供服務。在部署 Redis 主從的時候,需要將虛擬 IP 繫結到當前的 Redis 主節點。當主節點發生故障,比如機器故障、Redis 節點故障或者網路不可達,Sentinel 叢集會呼叫 client-reconfig-script
配置的指令碼,將 VIP 漂移到新的主節點上。
優點:
- 秒級切換,在 5s 內完成整個切換操作
- 指令碼自定義,架構可控
- 對應用透明,前端不用擔心後端發生什麼變化
缺點:
- 維護成本略高,Redis Sentinel 叢集建議投入 3 臺機器以上
- 使用 VIP 增加維護成本,存在 IP 混亂風險
- Sentinel 模式存在短時間的服務不可用
3.3 封裝客戶端直連 Redis Sentinel 埠
部分業務只能通過外網訪問 Redis,上述兩種方案均不可用,於是衍生出了這種方案。Web 使用客戶端連線其中一臺 Redis Sentinel 叢集中的一臺機器的某個埠,然後通過這個埠獲取到當前的主節點,然後再連線到真實的 Redis 主節點進行相應的業務員操作。需要注意的是,Redis Sentinel 埠和 Redis 主節點均需要開放訪問許可權。如果前端業務使用 Java,有 JedisSentinelPool 可以複用;如果前端業務使用 PHP,可以在 phpredis 的基礎上做二次封裝。
優點:
- 服務探測故障及時
- DBA 維護成本低
缺點:
- 依賴客戶端支援 Sentinel
- Sentinel 伺服器和 Redis 節點需要開放訪問許可權
- 對應用有侵入性
3.4 Redis Sentinel 叢集 + Keepalived/Haproxy
底層是 Redis Sentinel 叢集,代理著 Redis 主從,Web 端通過 VIP 提供服務。當主節點發生故障,比如機器故障、Redis 節點故障或者網路不可達,Redis 之間的切換通過 Redis Sentinel 內部機制保障,VIP 切換通過 Keepalived 保障。
優點:
- 秒級切換
- 對應用透明
缺點:
- 維護成本高
- 存在腦裂
- Sentinel 模式存在短時間的服務不可用
3.5 Redis M/S + Keepalived
此方案沒有使用到 Redis Sentinel。此方案使用了原生的主從和 Keepalived,VIP 切換通過 Keepalived 保障,Redis 主從之間的切換需要自定義指令碼實現。
優點:
- 秒級切換
- 對應用透明
- 部署簡單,維護成本低
缺點:
- 需要指令碼實現切換功能
- 存在腦裂
3.6 Redis Cluster
From: http://intro2libsys.com/focused-redis-topics/day-one/intro-redis-cluster
Redis 3.0.0 在 2015 年 4 月 2 日正式釋出,距今已有兩年多的時間。Redis 叢集採用 P2P 模式,無中心化。把 key 分成 16384 個 slot,每個例項負責一部分 slot。客戶端請求對應的資料,若該例項 slot 沒有對應的資料,該例項會轉發給對應的例項。另外,Redis 叢集通過 Gossip 協議同步節點資訊。
優點:
- 元件 all-in-box,部署簡單,節約機器資源
- 效能比 proxy 模式好
- 自動故障轉移、Slot 遷移中資料可用
- 官方原生叢集方案,更新與支援有保障
缺點:
- 架構比較新,最佳實踐較少
- 多鍵操作支援有限(驅動可以曲線救國)
- 為了效能提升,客戶端需要快取路由表資訊
- 節點發現、reshard 操作不夠自動化
3.7 Twemproxy
From: http://engineering.bloomreach.com/the-evolution-of-fault-tolerant-redis-cluster
多個同構 Twemproxy(配置相同)同時工作,接受客戶端的請求,根據 hash 演算法,轉發給對應的 Redis。
Twemproxy 方案比較成熟了,之前我們團隊長期使用此方案,但是效果並不是很理想。一方面是定位問題比較困難,另一方面是它對自動剔除節點的支援不是很友好。
優點:
- 開發簡單,對應用幾乎透明
- 歷史悠久,方案成熟
缺點:
- 代理影響效能
- LVS 和 Twemproxy 會有節點效能瓶頸
- Redis 擴容非常麻煩
- Twitter 內部已放棄使用該方案,新使用的架構未開源
3.8 Codis
From: https://github.com/CodisLabs/codis
Codis 是由豌豆莢開源的產品,涉及元件眾多,其中 ZooKeeper 存放路由表和代理節點後設資料、分發 Codis-Config 的命令;Codis-Config 是整合管理工具,有 Web 介面供使用;Codis-Proxy 是一個相容 Redis 協議的無狀態代理;Codis-Redis 基於 Redis 2.8 版本二次開發,加入 slot 支援,方便遷移資料。
優點:
- 開發簡單,對應用幾乎透明
- 效能比 Twemproxy 好
- 有圖形化介面,擴容容易,運維方便
缺點:
- 代理依舊影響效能
- 元件過多,需要很多機器資源
- 修改了 Redis 程式碼,導致和官方無法同步,新特性跟進緩慢
- 開發團隊準備主推基於 Redis 改造的 reborndb
0×04 最佳實踐
所謂的最佳實踐,都是最適合具體場景的實踐。
主推以下方案:
- Redis Sentinel 叢集 + 內網 DNS + 自定義指令碼
- Redis Sentinel 叢集 + VIP + 自定義指令碼
以下是實戰過程中總結出的最佳實踐:
- Redis Sentinel 叢集建議使用 >= 5 臺機器
- 不同的大業務可以使用一套 Redis Sentinel 叢集,代理該業務下的所有埠
- 根據不同的業務劃分好 Redis 埠範圍
- 自定義指令碼建議採用 Python 實現,擴充套件便利
- 自定義指令碼需要注意判斷當前的 Sentinel 角色
- 自定義指令碼傳入引數:<service_name> <role> <comment> <from_ip> <from_port> <to_ip> <to_port>
- 自定義指令碼需要遠端 ssh 操作機器,建議使用
paramiko
庫,避免重複建立 SSH 連線,消耗時間 - 加速 SSH 連線,建議關閉以下兩個引數
- UseDNS no
- GSSAPIAuthentication no
- 微信或者郵件告警,建議 fork 一個程式,避免主程式阻塞
- 自動切換和故障切換,所有操作建議在 15s 以內完成
0×05 小結
此次活動分享了 Redis 高可用的必要性、Sentinel 原理、Redis 高可用常用架構和實戰過程中總結出的最佳實踐,希望對讀者有所幫助,如果有需要後續交流的,可以新增我的微信(Wentasy),或者發郵件到:dbarobinwen@gmail.com
附 PPT 下載:https://github.com/dbarobin/slides
視訊回放:Redis 高可用架構最佳實踐
0×06 致謝
感謝聽雲和運維幫的精心組織,感謝大家冒著大雨前來參加此次活動。此次分享由 IT 大咖說全程錄影,感謝 IT 大咖說的技術支援。
0×07 參考
[1] jyzhou (2016-06-12). Redis 複製、Sentinel 的搭建和原理說明. Retrieved from http://www.cnblogs.com/zhoujinyi/p/5570024.html.
相關文章
- MySQL高可用架構案例篇:UCloud最佳實踐MySql架構Cloud
- MySQL高可用架構之MHA 原理與實踐MySql架構
- Redis高可用之戰:主從架構Redis架構
- 同程旅行基於 RocketMQ 高可用架構實踐MQ架構
- 深入高可用架構原理與實踐 書籍學習架構
- 高可用架構架構
- 大型網際網路高可用架構設計實踐2019架構
- 架構師日記-軟體高可用實踐那些事兒架構
- 微服務架構最佳實踐微服務架構
- 作業幫在多雲環境下的高可用雙活架構最佳化實踐架構
- MHA高可用架構的實現方式架構
- MySQL 實現高可用架構之 MHAMySql架構
- 分享:作業幫在多雲環境下的高可用雙活架構最佳化實踐架構
- MySQL 高可用架構之 MMM 架構MySql架構
- 雲中SQL Server高可用性最佳實踐SQLServer
- 京東短網址高可用提升最佳實踐
- Redis原理和高可用場景實踐總結Redis
- 資深架構師談Redis高可用架構的應用及改進架構Redis
- Mysql高可用架構方案MySql架構
- Canal高可用架構部署架構
- 實踐400+私有云打造的雲安全高可用架構詳解架構
- MySQL高可用架構:mysql+keepalived實現MySql架構
- 構建MHA實現MySQL高可用叢集架構MySql架構
- 微服務架構十條最佳實踐微服務架構
- 《MySQL效能優化和高可用架構實踐》簡介與推薦序MySql優化架構
- MySQL高可用架構對比MySql架構
- mysql高可用架構MHA搭建MySql架構
- AWS 高可用AWS架構方案架構
- SpringCloud 應用在 Kubernetes 上的最佳實踐 — 高可用(熔斷)SpringGCCloud
- 服務發現與配置管理高可用最佳實踐
- 編寫架構文件的最佳實踐 - Singh架構
- KubeSphere 最佳實戰:K8s 構建高可用、高效能 Redis 叢集實戰指南K8SRedis
- 教你用 3 臺機器搞定一個 Redis 高可用架構Redis架構
- MySQL高可用架構設計分析MySql架構
- k8s高可用架構K8S架構
- 深度解析KubeEdge EdgeMesh 高可用架構架構
- MQ系列9:高可用架構分析MQ架構
- Spring Cloud 應用在 Kubernetes 上的最佳實踐 — 高可用(混沌工程)SpringCloud
- SpringCloud 應用在 Kubernetes 上的最佳實踐 —— 高可用(容量評估)SpringGCCloud