如何搭建高可用redis架構?

1 題記

Redis 是一個開源的使用 ANSI C 語言編寫、支持網絡、可基於內存亦可持久化的日誌型、Key-Value 數據庫,並提供多種語言的 API。php

現在,互聯網業務的數據正以更快的速度在增加,數據類型愈來愈豐富,這對數據處理的速度和能力提出了更高要求。Redis 是一種開源的內存非關係型數據庫,給開發人員帶來的體驗是顛覆性的。在自始至終的設計過程當中,都充分考慮高性能,這使得 Redis 成爲當今速度最快的 NoSQL 數據庫。前端

考慮高性能的同時,高可用也是很重要的考慮因素。互聯網 7x24 無間斷服務,在故障期間以最快的速度 Failover,能給企業帶來最小的損失。git

那麼,在實際應用中,都有哪些高可用架構呢?架構之間有何優劣?咱們應該怎麼取捨?有哪些最佳實踐?github

2、Sentinel (哨兵)原理

在講解 Redis 高可用方案以前,咱們先來看看 Redis Sentinel 原理(https://redis.io/topics/sentinel)是怎麼樣的。redis

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]

3、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

接下來配合圖文逐個講解。

一、Redis Sentinel 集羣 + 內網 DNS + 自定義腳本

 

Redis Sentinel 集羣 + 內網 DNS + 自定義腳本

上圖是已經在線上環境應用的方案。底層是 Redis Sentinel 集羣,代理着 Redis 主從,Web 端鏈接內網 DNS 提供服務。內網 DNS 按照必定的規則分配,好比 xxxx.redis.cache/queue.port.xxx.xxx,第一個段表示業務簡寫,第二個段表示這是 Redis 內網域名,第三個段表示 Redis 類型,cache 表示緩存,queue 表示隊列,第四個段表示 Redis 端口,第5、第六個段表示內網主域名。

當主節點發生故障,好比機器故障、Redis 節點故障或者網絡不可達,Sentinel 集羣會調用 client-reconfig-script 配置的腳本,修改對應端口的內網域名。對應端口的內網域名指向新的 Redis 主節點。

優勢

秒級切換,在 10s 內完成整個切換操做

腳本自定義,架構可控

對應用透明,前端不用擔憂後端發生什麼變化

缺點:

維護成本略高,Redis Sentinel 集羣建議投入 3 臺機器以上

依賴 DNS,存在解析延時

Sentinel 模式存在短期的服務不可用

服務經過外網訪問不可採用此方案

二、Redis Sentinel 集羣 + VIP + 自定義腳本

 

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 Sentinel 端口

 

部分業務只能經過外網訪問 Redis,上述兩種方案均不可用,因而衍生出了這種方案。Web 使用客戶端鏈接其中一臺 Redis Sentinel 集羣中的一臺機器的某個端口,而後經過這個端口獲取到當前的主節點,而後再鏈接到真實的 Redis 主節點進行相應的業務員操做。須要注意的是,Redis Sentinel 端口和 Redis 主節點均須要開放訪問權限。若是前端業務使用 Java,有 JedisSentinelPool 能夠複用;若是前端業務使用 PHP,能夠在 phpredis 的基礎上作二次封裝。

優勢:

服務探測故障及時

DBA 維護成本低

缺點:

依賴客戶端支持 Sentinel

Sentinel 服務器和 Redis 節點須要開放訪問權限

對應用有侵入性

四、Redis Sentinel 集羣 + Keepalived/Haproxy

 

Redis Sentinel 集羣 + Keepalived/Haproxy

底層是 Redis Sentinel 集羣,代理着 Redis 主從,Web 端經過 VIP 提供服務。當主節點發生故障,好比機器故障、Redis 節點故障或者網絡不可達,Redis 之間的切換經過 Redis Sentinel 內部機制保障,VIP 切換經過 Keepalived 保障。

優勢:

秒級切換

對應用透明

缺點:

維護成本高

存在腦裂

Sentinel 模式存在短期的服務不可用

五、Redis M/S + Keepalived

 

Redis M/S + Keepalived

此方案沒有使用到 Redis Sentinel。此方案使用了原生的主從和 Keepalived,VIP 切換經過 Keepalived 保障,Redis 主從之間的切換須要自定義腳本實現。

優勢:

秒級切換

對應用透明

部署簡單,維護成本低

缺點:

須要腳本實現切換功能

存在腦裂

六、Redis Cluster

 

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 操做不夠自動化

七、Twemproxy

 

Twemproxy

From: http://engineering.bloomreach.com/the-evolution-of-fault-tolerant-redis-cluster

多個同構 Twemproxy(配置相同)同時工做,接受客戶端的請求,根據 hash 算法,轉發給對應的 Redis。

Twemproxy 方案比較成熟了,以前咱們團隊長期使用此方案,可是效果並非很理想。一方面是定位問題比較困難,另外一方面是它對自動剔除節點的支持不是很友好。

優勢:

開發簡單,對應用幾乎透明

歷史悠久,方案成熟

缺點:

代理影響性能

LVS 和 Twemproxy 會有節點性能瓶頸

Redis 擴容很是麻煩

Twitter 內部已放棄使用該方案,新使用的架構未開源

八、Codis

 

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

4、最佳實踐

所謂的最佳實踐,都是最適合具體場景的實踐。

主推如下方案:

Redis Sentinel 集羣 + 內網 DNS + 自定義腳本

Redis Sentinel 集羣 + VIP + 自定義腳本

如下是實戰過程當中總結出的最佳實踐:

Redis Sentinel 集羣建議使用 >= 5 臺機器

不一樣的大業務可使用一套 Redis Sentinel 集羣,代理該業務下的全部端口

根據不一樣的業務劃分好 Redis 端口範圍

自定義腳本建議採用 Python 實現,擴展便利

自定義腳本須要注意判斷當前的 Sentinel 角色

自定義腳本傳入參數:

自定義腳本須要遠程 ssh 操做機器,建議使用 paramiko 庫,避免重複創建 SSH 鏈接,消耗時間

加速 SSH 鏈接,建議關閉如下兩個參數

UseDNS no

GSSAPIAuthentication no

微信或者郵件告警,建議 fork 一個進程,避免主進程阻塞

自動切換和故障切換,全部操做建議在 15s 之內完成

針對上面的技術我特地整理了一下,有不少技術不是靠幾句話能講清楚,因此乾脆找朋友錄製了一些視頻,不少問題其實答案很簡單,可是背後的思考和邏輯不簡單,要作到知其然還要知其因此然。若是想學習Java工程化、高性能及分佈式、深刻淺出。性能調優、Spring,MyBatis,Netty源碼分析的朋友能夠後臺私信回覆「架構」 就能夠立刻免費得到

相關文章
相關標籤/搜索