溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

3臺機器如何搭建一個高可用Redis服務(wù)架構(gòu)

發(fā)布時間:2021-11-17 15:07:36 來源:億速云 閱讀:171 作者:小新 欄目:開發(fā)技術(shù)

這篇文章給大家分享的是有關(guān)3臺機器如何搭建一個高可用Redis服務(wù)架構(gòu)的內(nèi)容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。

基于內(nèi)存的 Redis 應(yīng)該是目前各種 Web 開發(fā)業(yè)務(wù)中最為常用的 key-value 數(shù)據(jù)庫了。

我們經(jīng)常在業(yè)務(wù)中用其存儲用戶登陸態(tài)(Session 存儲),加速一些熱數(shù)據(jù)的查詢(相比較 MySQL 而言,速度有數(shù)量級的提升),做簡單的消息隊列(LPUSH 和 BRPOP)、訂閱發(fā)布(PUB/SUB)系統(tǒng)等等。

規(guī)模比較大的互聯(lián)網(wǎng)公司,一般都會有專門的團隊,將 Redis 存儲以基礎(chǔ)服務(wù)的形式提供給各個業(yè)務(wù)調(diào)用。

不過任何一個基礎(chǔ)服務(wù)的提供方,都會被調(diào)用方問起的一個問題是:你的服務(wù)是否具有高可用性?***不要因為你的服務(wù)經(jīng)常出問題,導(dǎo)致我這邊的業(yè)務(wù)跟著遭殃。

最近在我的項目中自己搭了一套小型的“高可用”Redis 服務(wù),在此做一下自己的總結(jié)和思考。

首先我們要定義一下對于 Redis 服務(wù)來說怎樣才算是高可用,即在各種出現(xiàn)異常的情況下,依然可以正常提供服務(wù);或者寬松一些,出現(xiàn)異常的情況下,只經(jīng)過很短暫的時間即可恢復(fù)正常服務(wù)。

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

某個節(jié)點服務(wù)器的某個進程突然 down 掉,例如某開發(fā)手殘,把一臺服務(wù)器的 redis-server 進程 kill 了。

某臺節(jié)點服務(wù)器 down 掉,相當于這個節(jié)點上所有進程都停了,例如某運維手殘,把一個服務(wù)器的電源拔了;例如一些老舊機器出現(xiàn)硬件故障。

任意兩個節(jié)點服務(wù)器之間的通信中斷了,例如某臨時工手殘,把用于兩個機房通信的光纜挖斷了。

其實以上任意一種異常都是小概率事件,而做到高可用性的基本指導(dǎo)思想就是:多個小概率事件同時發(fā)生的概率可以忽略不計,只要我們設(shè)計的系統(tǒng)可以容忍短時間內(nèi)的單點故障,即可實現(xiàn)高可用性。

對于搭建高可用 Redis 服務(wù),網(wǎng)上已有了很多方案,例如 Keepalived、Codis、Twemproxy、Redis Sentinel。

其中 Codis 和 Twemproxy 主要是用于大規(guī)模的 Redis 集群中,也是在 Redis 官方發(fā)布 Redis Sentinel 之前 Twitter 和豌豆莢提供的開源解決方案。

我的業(yè)務(wù)中數(shù)據(jù)量并不大,所以搞集群服務(wù)反而是浪費機器了。最終在 Keepalived 和 Redis Sentinel 之間做了個選擇,選擇了官方的解決方案 Redis Sentinel。

Redis Sentinel 可以理解為一個監(jiān)控 Redis Server 服務(wù)是否正常的進程,并且一旦檢測到不正常,可以自動地將備份(slave)Redis Server 啟用,使得外部用戶對 Redis 服務(wù)內(nèi)部出現(xiàn)的異常無感知。

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

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

3臺機器如何搭建一個高可用Redis服務(wù)架構(gòu)

一般情況下,我們搭的個人網(wǎng)站或者平時做開發(fā)時,會起一個單實例的 Redis Server。

調(diào)用方直接連接 Redis 服務(wù)即可,甚至 Client 和 Redis 本身就處于同一臺服務(wù)器上。

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

一旦 Redis 服務(wù)進程掛了,或者服務(wù)器 1 停機了,那么服務(wù)就不可用了。并且如果沒有配置 Redis 數(shù)據(jù)持久化的話,Redis 內(nèi)部已經(jīng)存儲的數(shù)據(jù)也會丟失。

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

3臺機器如何搭建一個高可用Redis服務(wù)架構(gòu)

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

與此同時,在額外啟動一個 Sentinel 進程,監(jiān)控兩個 Redis Server 實例的可用性,以便在 master 掛掉的時候,及時把 slave 提升到 master 的角色繼續(xù)提供服務(wù),這樣就實現(xiàn)了 Redis Server 的高可用。

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

對于 Redis 服務(wù)的調(diào)用方來說,現(xiàn)在要連接的是 Redis Sentinel 服務(wù),而不是 Redis Server 了。

常見的調(diào)用過程是,client 先連接 Redis Sentinel 并詢問目前 Redis Server 中哪個服務(wù)是 master,哪些是 slave,然后再去連接相應(yīng)的 Redis Server 進行操作。

當然目前的第三方庫一般都已經(jīng)實現(xiàn)了這一調(diào)用過程,不再需要我們手動去實現(xiàn)(例如 Nodejs 的 ioredis,PHP 的 predis,Golang 的 go-redis/redis,Java 的 jedis 等)。

然而,我們實現(xiàn)了 Redis Server 服務(wù)的主從切換之后,又引入了一個新的問題,即 Redis Sentinel 本身也是個單點服務(wù),一旦 Sentinel 進程掛了,那么客戶端就沒辦法鏈接 Sentinel 了。所以說,方案 2 的配置無法實現(xiàn)高可用性。

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

3臺機器如何搭建一個高可用Redis服務(wù)架構(gòu)

為了解決方案 2 的問題,我們把 Redis Sentinel 進程也額外啟動一份,兩個 Sentinel 進程同時為客戶端提供服務(wù)發(fā)現(xiàn)的功能。

對于客戶端來說,它可以連接任何一個 Redis Sentinel 服務(wù),來獲取當前 Redis Server 實例的基本信息。

通常情況下,我們會在 Client 端配置多個 Redis Sentinel 的鏈接地址,Client 一旦發(fā)現(xiàn)某個地址連接不上,會去試圖連接其他的 Sentinel 實例。

這當然也不需要我們手動實現(xiàn),各個開發(fā)語言中比較熱門的 Redis 連接庫都幫我們實現(xiàn)了這個功能。

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

然而,愿景是美好的,現(xiàn)實卻是很殘酷的。如此架構(gòu)下,依然無法實現(xiàn) Redis 服務(wù)的高可用。

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

這時,Sentinel 其實是不會將僅剩的 slave 切換成 master 繼續(xù)服務(wù)的,也就導(dǎo)致 Redis 服務(wù)不可用,因為 Redis 的設(shè)定是只有當超過 50% 的 Sentinel 進程可以連通并投票選取新的 master 時,才會真正發(fā)生主從切換。

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

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

試想一下異常 3,即服務(wù)器 1 和服務(wù)器 2 之間的網(wǎng)絡(luò)中斷,但是服務(wù)器本身是可以運行的,如下圖所示:

3臺機器如何搭建一個高可用Redis服務(wù)架構(gòu)

實際上對于服務(wù)器 2 來說,服務(wù)器 1 直接宕機和服務(wù)器 1 網(wǎng)絡(luò)連不通是一樣的效果,都是突然就無法進行任何通信了。

假設(shè)網(wǎng)絡(luò)中斷時我們允許服務(wù)器 2 的 Sentinel 把 slave 切換為 master,結(jié)果就是你現(xiàn)在擁有了兩個可以對外提供服務(wù)的 Redis Server。

Client 做任何的增刪改操作,有可能落在服務(wù)器 1 的 Redis 上,也有可能落在服務(wù)器 2 的 Redis 上(取決于 Client 到底連通的是哪個 Sentinel),造成數(shù)據(jù)混亂。

即使后面服務(wù)器1和服務(wù)器2之間的網(wǎng)絡(luò)又恢復(fù)了,我們也無法把數(shù)據(jù)統(tǒng)一了(兩份不一樣的數(shù)據(jù),到底該信任誰呢?),數(shù)據(jù)一致性完全被破壞。

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

3臺機器如何搭建一個高可用Redis服務(wù)架構(gòu)

鑒于方案 3 并沒有辦法做到高可用,我們最終的版本就是上圖所示的方案 4 了,實際上這就是我們最終搭建的架構(gòu)。

我們引入了服務(wù)器 3,并且在 3 上面又搭建起一個 Redis Sentinel 進程,現(xiàn)在由三個 Sentinel 進程來管理兩個 Redis Server 實例。

這種場景下,不管是單一進程故障、還是單個機器故障、還是某兩個機器網(wǎng)絡(luò)通信故障,都可以繼續(xù)對外提供 Redis 服務(wù)。

實際上,如果你的機器比較空閑,當然也可以把服務(wù)器 3 上面也開啟一個 Redis Server,形成 1 master + 2 slave 的架構(gòu)。

每個數(shù)據(jù)都有兩個備份,可用性會提升一些。當然也并不是 slave 越多越好,畢竟主從同步也是需要時間成本的。

在方案 4 中,一旦服務(wù)器 1 和其他服務(wù)器的通信完全中斷,那么服務(wù)器 2 和 3 會將 slave 切換為 master。

對于客戶端來說,在這么一瞬間會有 2 個 master 提供服務(wù),并且一旦網(wǎng)絡(luò)恢復(fù)了,那么所有在中斷期間落在服務(wù)器 1 上的新數(shù)據(jù)都會丟失。

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

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

只不過在公司里面,一般服務(wù)的提供方和調(diào)用方并不來自同一個團隊。兩個團隊共同操作同一個機器,很容易因為溝通問題導(dǎo)致一些誤操作,所以出于這種人為因素的考慮,我們還是采用了方案 4 的架構(gòu)。

并且由于服務(wù)器 3 上面只跑了一個 Sentinel 進程,對服務(wù)器資源消耗并不多,還可以用服務(wù)器 3 來跑一些其他的服務(wù)。

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

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

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

而改造成 Sentinel 模式之后,Client 不得不采用一些支持 Sentinel 模式的外部依賴包,并且還要修改自己的 Redis 連接配置,這對于“矯情”的用戶來講顯然是不能接收的。

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

3臺機器如何搭建一個高可用Redis服務(wù)架構(gòu)

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

我們可以把虛擬 IP 指向 Redis Server master 所在的服務(wù)器,在發(fā)生 Redis 主從切換的時候,會觸發(fā)一個回調(diào)腳本,回調(diào)腳本中將 VIP 切換至 slave 所在的服務(wù)器。

這樣對于 Client 端來說,他仿佛在使用的依然是一個單機版的高可用 Redis 服務(wù)。

感謝各位的閱讀!關(guān)于“3臺機器如何搭建一個高可用Redis服務(wù)架構(gòu)”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI