1. 程式人生 > >3臺機器輕鬆搭建一個高可用Redis服務架構

3臺機器輕鬆搭建一個高可用Redis服務架構

最近在我的專案中自己搭了一套小型的“高可用”Redis 服務,在此做一下總結和思考。

640?wx_fmt=png

基於記憶體的 Redis 應該是目前各種 Web 開發業務中最為常用的 key-value 資料庫了。

我們經常在業務中用其儲存使用者登陸態(Session 儲存),加速一些熱資料的查詢(相比較 MySQL 而言,速度有數量級的提升),做簡單的訊息佇列(LPUSH 和 BRPOP)、訂閱釋出(PUB/SUB)系統等等。

規模比較大的網際網路公司,一般都會有專門的團隊,將 Redis 儲存以基礎服務的形式提供給各個業務呼叫。

不過任何一個基礎服務的提供方,都會被呼叫方問起的一個問題是:你的服務是否具有高可用性?最好不要因為你的服務經常出問題,導致我這邊的業務跟著遭殃。

最近在我的專案中自己搭了一套小型的“高可用Redis 服務,在此做一下自己的總結和思考。

首先我們要定義一下對於 Redis 服務來說怎樣才算是高可用,即在各種出現異常的情況下,依然可以正常提供服務;或者寬鬆一些,出現異常的情況下,只經過很短暫的時間即可恢復正常服務。

所謂異常,應該至少包含了以下三種可能性:

  • 某個節點伺服器的某個程序突然 down 掉,例如某開發手殘,把一臺伺服器的 redis-server 程序 kill 了。

  • 某臺節點伺服器 down 掉,相當於這個節點上所有程序都停了,例如某運維手殘,把一個伺服器的電源拔了;例如一些老舊機器出現硬體故障。

  • 任意兩個節點伺服器之間的通訊中斷了,例如某臨時工手殘,把用於兩個機房通訊的光纜挖斷了。

其實以上任意一種異常都是小概率事件,而做到高可用性的基本指導思想就是:多個小概率事件同時發生的概率可以忽略不計,只要我們設計的系統可以容忍短時間內的單點故障,即可實現高可用性。

對於搭建高可用 Redis 服務,網上已有了很多方案,例如 Keepalived、CodisTwemproxyRedis Sentinel。

其中 Codis 和 Twemproxy 主要是用於大規模的 Redis 叢集中,也是在 Redis 官方釋出 Redis Sentinel 之前 Twitter 和豌豆莢提供的開源解決方案。

我的業務中資料量並不大,所以搞叢集服務反而是浪費機器了。最終在 Keepalived 和 Redis Sentinel 之間做了個選擇,選擇了官方的解決方案 Redis Sentinel。

Redis Sentinel 可以理解為一個監控 Redis Server 服務是否正常的程序,並且一旦檢測到不正常,可以自動地將備份(slave)Redis Server 啟用,使得外部使用者對 Redis 服務內部出現的異常無感知。

下面我們按照由簡至繁的步驟,搭建一個最小型的高可用的 Redis 服務。

方案1:單機版 Redis Server,無 Sentinel

640?wx_fmt=png

一般情況下,我們搭的個人網站或者平時做開發時,會起一個單例項的 Redis Server。

呼叫方直接連線 Redis 服務即可,甚至 Client 和 Redis 本身就處於同一臺伺服器上。

這種搭配僅適合個人學習娛樂,畢竟這種配置總會有單點故障的問題無法解決。

一旦 Redis 服務程序掛了,或者伺服器 1 停機了,那麼服務就不可用了。並且如果沒有配置 Redis 資料持久化的話,Redis 內部已經儲存的資料也會丟失。

方案2:主從同步 Redis Server,單例項 Sentinel

640?wx_fmt=png

為了實現高可用,解決方案 1 中所述的單點故障問題,我們必須增加一個備份服務,即在兩臺伺服器上分別啟動一個 Redis Server 程序,一般情況下由 master 提供服務,slave 只負責同步和備份。

與此同時,在額外啟動一個 Sentinel 程序,監控兩個 Redis Server 例項的可用性,以便在 master 掛掉的時候,及時把 slave 提升到 master 的角色繼續提供服務,這樣就實現了 Redis Server 的高可用。

這基於一個高可用服務設計的依據,即單點故障本身就是個小概率事件,而多個單點同時故障(即 master 和 slave 同時掛掉),可以認為是(基本)不可能發生的事件。

對於 Redis 服務的呼叫方來說,現在要連線的是 Redis Sentinel 服務,而不是 Redis Server 了。

常見的呼叫過程是,client 先連線 Redis Sentinel 並詢問目前 Redis Server 中哪個服務是 master,哪些是 slave,然後再去連線相應的 Redis Server 進行操作。

當然目前的第三方庫一般都已經實現了這一呼叫過程,不再需要我們手動去實現(例如 Nodejs 的 ioredis,PHP 的 predis,Golang 的 go-redis/redis,Java 的 jedis 等)。

然而,我們實現了 Redis Server 服務的主從切換之後,又引入了一個新的問題,即 Redis Sentinel 本身也是個單點服務,一旦 Sentinel 程序掛了,那麼客戶端就沒辦法連結 Sentinel 了。所以說,方案 2 的配置無法實現高可用性。

方案3:主從同步 Redis Server,雙例項 Sentinel

640?wx_fmt=png

為了解決方案 2 的問題,我們把 Redis Sentinel 程序也額外啟動一份,兩個 Sentinel 程序同時為客戶端提供服務發現的功能。

對於客戶端來說,它可以連線任何一個 Redis Sentinel 服務,來獲取當前 Redis Server 例項的基本資訊。

通常情況下,我們會在 Client 端配置多個 Redis Sentinel 的連結地址,Client 一旦發現某個地址連線不上,會去試圖連線其他的 Sentinel 例項。

這當然也不需要我們手動實現,各個開發語言中比較熱門的 Redis 連線庫都幫我們實現了這個功能。

我們預期是:即使其中一個 Redis Sentinel 掛掉了,還有另外一個 Sentinel 可以提供服務。

然而,願景是美好的,現實卻是很殘酷的。如此架構下,依然無法實現 Redis 服務的高可用。

方案 3 示意圖中,紅線部分是兩臺伺服器之間的通訊,而我們所設想的異常場景(異常2)是:某臺伺服器整體宕機,不妨假設伺服器 1 停機,此時,只剩下伺服器 2 上面的 Redis Sentinel 和 slave Redis Server 程序。

這時,Sentinel 其實是不會將僅剩的 slave 切換成 master 繼續服務的,也就導致 Redis 服務不可用,因為 Redis 的設定是隻有當超過 50% 的 Sentinel 程序可以連通並投票選取新的 master 時,才會真正發生主從切換。

本例中兩個 Sentinel 只有一個可以連通,等於 50% 並不在可以主從切換的場景中。

你可能會問,為什麼 Redis 要有這個 50% 的設定?假設我們允許小於等於 50% 的 Sentinel 連通的場景下也可以進行主從切換呢?

試想一下異常 3,即伺服器 1 和伺服器 2 之間的網路中斷,但是伺服器本身是可以執行的,如下圖所示:

640?wx_fmt=png

實際上對於伺服器 2 來說,伺服器 1 直接宕機和伺服器 1 網路連不通是一樣的效果,都是突然就無法進行任何通訊了。

假設網路中斷時我們允許伺服器 2 的 Sentinel 把 slave 切換為 master,結果就是你現在擁有了兩個可以對外提供服務的 Redis Server。

Client 做任何的增刪改操作,有可能落在伺服器 1 的 Redis 上,也有可能落在伺服器 2 的 Redis 上(取決於 Client 到底連通的是哪個 Sentinel),造成資料混亂。

即使後面伺服器1和伺服器2之間的網路又恢復了,我們也無法把資料統一了(兩份不一樣的資料,到底該信任誰呢?),資料一致性完全被破壞。

方案4:主從同步 Redis Server,三例項 Sentinel

640?wx_fmt=png

鑑於方案 3 並沒有辦法做到高可用,我們最終的版本就是上圖所示的方案 4 了,實際上這就是我們最終搭建的架構。

我們引入了伺服器 3,並且在 3 上面又搭建起一個 Redis Sentinel 程序,現在由三個 Sentinel 程序來管理兩個 Redis Server 例項。

這種場景下,不管是單一程序故障、還是單個機器故障、還是某兩個機器網路通訊故障,都可以繼續對外提供 Redis 服務。

實際上,如果你的機器比較空閒,當然也可以把伺服器 3 上面也開啟一個 Redis Server,形成 1 master + 2 slave 的架構。

每個資料都有兩個備份,可用性會提升一些。當然也並不是 slave 越多越好,畢竟主從同步也是需要時間成本的。

在方案 4 中,一旦伺服器 1 和其他伺服器的通訊完全中斷,那麼伺服器 2 和 3 會將 slave 切換為 master。

對於客戶端來說,在這麼一瞬間會有 2 個 master 提供服務,並且一旦網路恢復了,那麼所有在中斷期間落在伺服器 1 上的新資料都會丟失。

如果想要部分解決這個問題,可以配置 Redis Server 程序,讓其在檢測到自己網路有問題的時候,立即停止服務,避免在網路故障期間還有新資料進來(可以參考 Redis 的 min-slaves-to-write 和 min-slaves-max-lag 這兩個配置項)。

至此,我們就用 3 臺機器搭建了一個高可用的 Redis 服務。其實網上還有更加節省機器的辦法,就是把一個 Sentinel 程序放在 Client 機器上,而不是服務提供方的機器上。

只不過在公司裡面,一般服務的提供方和呼叫方並不來自同一個團隊。兩個團隊共同操作同一個機器,很容易因為溝通問題導致一些誤操作,所以出於這種人為因素的考慮,我們還是採用了方案 4 的架構。

並且由於伺服器 3 上面只跑了一個 Sentinel 程序,對伺服器資源消耗並不多,還可以用伺服器 3 來跑一些其他的服務。

易用性:像使用單機版 Redis 一樣使用 Redis Sentinel

作為服務的提供方,我們總是會講到使用者體驗問題。在上述方案當中始終有一個讓 Client 端用的不是那麼舒服的地方。

對於單機版 Redis,Client 端直接連線 Redis Server,我們只需要給一個 ip 和 port,Client 就可以使用我們的服務了。

而改造成 Sentinel 模式之後,Client 不得不採用一些支援 Sentinel 模式的外部依賴包,並且還要修改自己的 Redis 連線配置,這對於“矯情”的使用者來講顯然是不能接收的。

有沒有辦法還是像在使用單機版的 Redis 那樣,只給 Client 一個固定的 ip 和 port 就可以提供服務呢?

640?wx_fmt=png

答案當然是肯定的。這可能就要引入虛擬 IP(Virtual IP,VIP),如上圖所示。

我們可以把虛擬 IP 指向 Redis Server master 所在的伺服器,在發生 Redis 主從切換的時候,會觸發一個回撥指令碼,回撥指令碼中將 VIP 切換至 slave 所在的伺服器。

這樣對於 Client 端來說,他彷彿在使用的依然是一個單機版的高可用 Redis 服務。

結語

搭建任何一個服務,做到“能用”其實是非常簡單的,就像我們執行一個單機版的 Redis。

不過一旦要做到“高可用”,事情就會變得複雜起來。業務中使用了額外的兩臺伺服器,3 個 Sentinel 程序+1 個 Slave 程序,只是為了保證在那小概率的事故中依然做到服務可用。

在實際業務中我們還啟用了 supervisor 做程序監控,一旦程序意外退出,會自動嘗試重新啟動。

作者:HorstXu

編輯:陶家龍、孫淑娟

來源:轉載自http://www.cnblogs.com/xuning/p/8464625.html

Java高階架構 乾貨|學習640?wx_fmt=png640?wx_fmt=png長按,識別二維碼,加關注

溫馨提示

如果你喜歡本文,請分享到朋友圈,想要獲得更多資訊,請關注我。關注本文說說你的看法吧,下方評論哦

相關推薦

3機器輕鬆搭建一個可用Redis服務架構

“最近在我的專案中自己搭了一套小型的“高可用”Redis 服務,在此做一下總結和思考。基於記憶體

可用Redis服務架構分析與搭建

alt server proxy 基於 監控 接收 不可 slaves -s 基於內存的Redis應該是目前各種web開發業務中最為常用的key-value數據庫了,我們經常在業務中用其存儲用戶登陸態(Session存儲),加速一些熱數據的查詢(相比較mysql而言,速度有

可用Redis服務架構分析與搭建

size 回調 運行 .com red 復雜 指導 地址 ado 基於內存的Redis應該是目前各種Web開發業務中最為常用的Key-Value數據庫了,我們經常在業務中用其存儲用戶登陸態(Session存儲),加速一些熱數據的查詢(相比較MySQL而言,速度有數量級的提升

階段總結——用虛擬機器搭建一個可用負載均衡叢集架構

搭建一個高可用負載均衡叢集架構出來,並執行三個站點,具體需求如下。 ------------------------------------------------------------------------------------------ 基礎: 1 設計你認為合理的架構,用visio把架構圖

SpringCloud學習系列之一 ----- 搭建一個可用的註冊中心(Eureka)

字母 cat ted drivers 路由 都沒有 timer sessions order 前言 本篇主要介紹的是SpringCloud相關知識、微服務架構以及搭建一個高可用的服務註冊與發現的服務模塊(Eureka)。 SpringCloud介紹 Spring Clou

如何搭建一個可用的Eureka Server

1、新建一個SpringBoot工程,pom檔案中加上相關依賴: <!-- springcloud依賴 --> <dependencyManagement> <dependencies> <dependen

如何搭建可用Redis服務

題記基於記憶體的Redis應該是目前各種web開發業務中最為常用的key-value資料庫了,我們經常在業務中用其儲存使用者登陸態(Session儲存),加速一些熱資料的查詢(相比較mysql而言,速度有數量級的提升),做簡單的訊息佇列(LPUSH和BRPOP)、訂閱釋出(P

centos7 搭建ha(可用)hadoop2.7.3叢集

寫在前面 作為一個單體應用開發人員對於理解分散式應用和微服務的理論還可以。但是部署分散式環境來說還是一個挑戰。最近在學習hadoop,正也把學習的東西分享出來,希望幫助感興趣的人。 前面一章寫了centos7搭建hadoop叢集 再跟著做本章實驗前建議初學

一張圖講解最少機器搭建FastDFS可用分散式叢集安裝說明

 很幸運參與零售雲快消平臺的公有云搭建及孵化專案。零售雲快消平臺源於零售雲家電3C平臺私有專案,是與公司業務強耦合的。為了適用於全場景全品類平臺,集團要求專案平臺化,我們搶先並承擔了此任務。並由我來主要負責平臺建設及專案落地。  今天講解在零售雲快消平臺中使用的圖片服務FastDFS叢集搭建說明,此叢集模式是

塗抹mysql筆記-搭建mysql可用體系

argument 並且 ren enum 記錄 ica 操作系統 ner 一份 mysql的高可用體系<>追求更高穩定性的服務體系 可擴展性:橫向擴展(增加節點)、縱向擴展(增加節點的硬件配置) 高可用性<>Slave+LVS+Keepalived實

LVS-DR+keepalived 搭建web可用負載均衡

lvs-dr+keepalived配置實驗環境 redhat6.5 2.6.32-431.el6.x86_64 keepalived-1.2.16版本ipvsadm-1.26-2.el6.x86_64所有的虛擬機 都 關閉防火墻和selinux 配置好了本地yum源搭建要求是對LVS-DR模式的原理熟

mysql+mycat搭建穩定可用集群,負載均衡,主備復制,讀寫分離

root用戶 架構 .bat 出現 內存 ace 權威指南 上層 復制 主要思路 測試環境 實現mysql主備復制 配置A主mysql 配置B備mysql 驗證同步配置結果 驗證是否同步 關閉B備mysql的同步,驗證讀寫分離

通過keepalived搭建lvs可用集群

linux 負載均衡集群 keepalived1.配置keepalived Keepalived的配置僅需要一個配置文件即可完成對HA cluster和LVS服務節點監控,在通過Keepalived搭建高可用的LVS集群實例中,主、備Director Server都需要安裝Keepalived軟件,安裝成功

通過heartbeat搭建lvs可用性集群

linux heartbeat lvs 集群首先,在主、備節點上配置lvs信息,一般通過ldirectord配置在搭建Director Server的雙機熱備系統之前,首先需要在兩臺主機上安裝heartbeat軟件,安裝軟件後在/etc/ha.d/ha.cf產生主配置文件1.配置heartbeat的主配置文件

通過piranha搭建lvs可用集群

linux lvs piranha piranha是Redhat提供一個基於web的lvs配置軟件,通過piranha可以省去手工配置lvs的繁瑣工作。同時,piranha也可以單獨提供集群功能,例如,可以通過piranha激活Director Server的備用主機。這裏利用piranha來配置

搭建MySQL可用負載均衡集群

分別是 $? 啟動腳本 hang 常見 ase 說明 配置步驟 分享 閱讀目錄1、簡介2、基本環境3、配置MySQL主主復制4、中間件簡述  4.1、Haproxy介紹  4.2、keepalived介紹5、中間件的安裝與配置(haproxy、keepalived)  5.

用簡單的方法構建一個可用服務

高可用 架構 redis 服務器 一. 什麽是高可用性 服務端,顧名思義就是為用戶提供服務的。停工時間,就是不能向用戶提供服務的時間。高可用,就是系統具有高度可用性,盡量減少停工時間。 停工的原因一般有: 服務器故障。例如服務器宕機,服務器網絡出現問題,機房或者機架出現問題等。訪問量急劇上升,

圖文:Linux-DNS主備服務搭建可用

重啟 slave 配置文件 服務器 image http img -a 建立 DNS主服務器(master):192.168.127.147從服務器(slave):192.168.127.1481、首先在master和slave上安裝DNS包: 2、編輯master上的D

MMM+Amoeba搭建MySQL可用負載均衡群集

模擬 關閉防火墻 同步服務 lan 基礎上 拓撲 編譯安裝mysql 時鐘 命令行 MySQL的主從復制和MySQL的讀寫分離兩者有著緊密聯系,首先要部署主從復制,只有主從復制完成了,才能在此基礎上進行數據的讀寫分離。MySQL的讀寫分離就是只在主服務器上寫,只在從服務器上

如何打造一個可用多租戶的企業級Maven私有倉庫服務

href 雲效 repl group abi 方式 簽名 ava watermark 摘要: 為什麽要打造多租戶的企業級Maven私有倉庫服務? 在Java的世界中,我們通常使用Maven的依賴體系來管理構件(artifact,又稱為二方庫或三方庫)的依賴。Maven倉庫用