Redis 分布式高可用終極指南

最近項目上需要用到 redis 高可用方案,遂上網(wǎng)找了一些資料學(xué)習(xí),但是網(wǎng)上關(guān)于 redis 高可用的幾種實現(xiàn)方式或口徑不一子库,或含糊不清睁冬,或缺斤少兩。經(jīng)歷了多方資料學(xué)習(xí)和實際驗證溉贿,本文試圖將 redis 分布式和集群方案從概念理解到技術(shù)選型到搭建使的整個過程用最簡單的語言講述清楚枫吧。

分布式與集群

下文會涉及到大量的分布式和集群術(shù)語,這里我們先來復(fù)習(xí)一下集群和分布式的概念宇色,加深一下理解九杂。

目前的項目很少會采用單機架構(gòu)了,一是因為單機性能有限代兵,二是因為單機服務(wù)一旦故障整個系統(tǒng)就無法繼續(xù)提供服務(wù)了尼酿。所以目前集群和分布式的架構(gòu)使用得很廣泛,主要就是為了解決上述兩個問題植影,一個性能問題裳擎,一個故障問題,通過分布式架構(gòu)解決性能(高并發(fā))問題思币,通過集群架構(gòu)解決故障服務(wù)(高可用)問題鹿响。

分布式架構(gòu)

分布式:一個業(yè)務(wù)分拆多個子業(yè)務(wù),部署在不同的服務(wù)器上

網(wǎng)上很多文章把分布式架構(gòu)說得很復(fù)雜谷饿,但都沒有切中關(guān)鍵惶我,其實理解起來很簡單,所有的計算機系統(tǒng)都是為業(yè)務(wù)服務(wù)的博投,將同一個業(yè)務(wù)拆分成多個子業(yè)務(wù)绸贡,各個子業(yè)務(wù)部署在不同的服務(wù)器上,這就是分布式架構(gòu)毅哗,通過將業(yè)務(wù)拆細(xì)听怕,為不同的子業(yè)務(wù)配置不同性能的服務(wù)器,提高整個系統(tǒng)的性能虑绵。我個人認(rèn)為目前很火的微服務(wù)概念其實本質(zhì)上就是分布式尿瞭。

按照類型大致可以分為兩種:分布式計算分布式存儲

分布式計算很好理解翅睛,就是將大量計算任務(wù)分配到多個計算單元上以提高總計算性能声搁。例如暴力破解某個密碼需要遍歷某個字符組合10萬次黑竞,假設(shè)一臺計算機需要10分鐘,那么10臺計算機同時遍歷疏旨,每臺遍歷1萬次很魂,最后將結(jié)果匯總,那么就只需要1分鐘檐涝。這10臺計算機組合起來就是一個分布式計算系統(tǒng)莫换,這里的業(yè)務(wù)就是計算。

同理骤铃,分布式儲存也很好理解拉岁,就是將大量數(shù)據(jù)分配到多個儲存單元上以提高總存儲量。例如100ZB的數(shù)據(jù)一個儲存單元放不下惰爬,那就拆成100份喊暖,每個儲存單元存1份,那么這100個存儲單元組合起來就是一個分布式儲存系統(tǒng)撕瞧,這里的業(yè)務(wù)就是存儲陵叽。目前主流的關(guān)系型數(shù)據(jù)庫都有比較成熟的分布式存儲方案,如 MySQL 的 MySQL Fabric丛版、MyCat 等巩掺,Oracle Database 有Oracle Sharding 等。Redis 作為流行的非關(guān)系型數(shù)據(jù)庫页畦,由于是內(nèi)存數(shù)據(jù)庫胖替,理論上一般不會在 Redis 中存放太多的數(shù)據(jù),但是在某些特殊情況下還是會有儲存空間不夠的情況豫缨,或者需要預(yù)防儲存空間不夠的情況發(fā)生独令,這個時候就需要 Redis 分布式架構(gòu)了。

例如某集團(tuán)下有很多的子公司好芭,每個子公司都有多套 IT 系統(tǒng)燃箭,其中很多 IT 系統(tǒng)都是需要使用 Redis 的,集團(tuán)為了統(tǒng)一管理舍败,搭建了一套中央 Redis 系統(tǒng)招狸,要求所有子公司下的 IT 系統(tǒng)統(tǒng)一使用集團(tuán)的中央 Redis 庫,這個時候即使當(dāng)前儲存容量夠用邻薯,但是為了應(yīng)對后期發(fā)展就必須使用到分布式儲存裙戏,因為分布式架構(gòu)理論上都支持無限水平拓展。

集群架構(gòu)

集群:同一個業(yè)務(wù)弛说,部署在多個服務(wù)器上

集群同樣也非常好理解挽懦,就是在多個服務(wù)器上部署同一個業(yè)務(wù)翰意,這樣可以起到兩個作用:

  1. 分散每臺服務(wù)器的壓力
  2. 任意一臺或者幾臺服務(wù)器宕機也不會影響整個系統(tǒng)

例如一個典型的 Web 集群服務(wù)架構(gòu)圖如下:

一個典型的 Web 集群架構(gòu)圖

這里三個 Web Server 服務(wù)器實際上都是運行著同一套業(yè)務(wù)木人,但是三臺服務(wù)器就可以顯著分散單臺服務(wù)器壓力信柿,并且任意一臺宕機也不會導(dǎo)致無法提供服務(wù)。

分布式與集群的關(guān)系

分布式和集群區(qū)別很好理解醒第,用下面一張圖表示:

分布式與集群的區(qū)別

需要注意的是分布式不一定能用上渔嚷,但是集群一般都是需要的。因為不是所有系統(tǒng)都需要應(yīng)對高并發(fā)場景稠曼,但高可用是一個系統(tǒng)能夠長期穩(wěn)定運行基本保障形病。因此用到分布式架構(gòu)的系統(tǒng)基本上都會用到集群,而用集群架構(gòu)的系統(tǒng)卻不一定會用到分布式霞幅。

Redis 部署指南

單節(jié)點方案:Redis Standalone

原理簡介

這是最簡單的 redis 部署方案漠吻,所有數(shù)據(jù)存儲和讀寫操作都在同一個 redis 服務(wù)上。

這種方式優(yōu)點很明顯:部署簡單司恳,無論是部署成本還是運維成本都很低途乃,本地測試時最常見也是最方便的方式。

但同時缺點也很明顯:不能實現(xiàn)高可用扔傅,也不能應(yīng)對高并發(fā)場景耍共,也無法輕易水平拓展,數(shù)據(jù)儲存量很容易見頂猎塞。

部署實例

單節(jié)點模式的部署是最簡單的试读,一下是 Linux 系統(tǒng)下部署單節(jié)點 redis 的方法:

# 下載 Redis 二進(jìn)制安裝包:
wget http://download.redis.io/releases/redis-5.0.4.tar.gz
# 解壓二進(jìn)制包
tar –zxvf redis-5.0.4.tar.gz
# 進(jìn)入解壓文件夾并編譯二進(jìn)制文件
cd redis-5.0.4
make
# 安裝
cd src
make test
make install

在 make install 和 make test 的時候可能會遇到下面這個問題:

You need tcl 8.5 or newer in order to run the Redis test
make: *** [test] Error 1

這是因為系統(tǒng)中的 TCL 語言版本太低,TCL 語言是一種工具腳本語言荠耽,在安裝 Redis 的過程中 make test 命令需要用到這個腳本語言钩骇,這個時候我們需要升級一下系統(tǒng)中的 TCL 版本:

# 下載一個高于 8.5 版本的 TCL 安裝包,比如 8.6.8
wget http://downloads.sourceforge.net/tcl/tcl8.6.8-src.tar.gz
# 解壓
tar -zxvf tcl8.6.8-src.tar.gz  -C /usr/local/  
# 切換到解壓后的源碼目錄
cd  /usr/local/tcl8.6.8/unix/
# 編譯和安裝
sudo ./configure  
sudo make  
sudo make install

升級 TCL 到 8.5 版本以后铝量,繼續(xù)執(zhí)行之前報錯的語句伊履,完成 Redis 的安裝,安裝完成后用 redis-server -v 驗證安裝是否成功款违,若成功輸出如下版本信息則代表安裝成功:

Redis server v=5.0.4

安裝成功就可以直接運行了唐瀑,但是默認(rèn)配置下是不支持后臺運行的,觀點命令窗口就會結(jié)束 redis 進(jìn)程插爹,這顯然是不行的哄辣。所以我們再簡單改一下 redis 的配置,讓其能夠直接后臺運行赠尾。

# 進(jìn)入到 redis 的安裝目錄力穗,編輯 redis.conf
vim /usr/redis/redis-5.0.4/redis.conf
# 將 daemonize no 修改成 daemonize yes (使 redis 服務(wù)可以在后臺運行)

# 在指定配置下運行redis服務(wù)
/usr/local/bin/redis-server /usr/redis/redis-5.0.4/redis.conf 
# 查看redis運行情況
ps -ef | grep redis

# 輸出
app   21794   1  0 Jan28 ?  03:31:25 ./redis-server *:6379

可以看到 redis 在默認(rèn)的 6379 端口下運行,配置文件中還有一些可以調(diào)整的地方气嫁,這里就不一一列舉了当窗。

那么單節(jié)點模式 redis 服務(wù)就部署完成了

Redis 高可用方案:Redis Sentinel

原理簡介

Redis Sentinel 是 Redis 官方推薦的高可用性(HA)解決方案,這是生產(chǎn)環(huán)境中最實用也是最常用的方案寸宵。

這里涉及到另一個概念:master-slaver(主從模式)崖面。很好理解元咙,就是常用的主備模式,例如 nginx 的主備模式巫员。一個主 redis 節(jié)點可以配置多個從節(jié)點庶香,當(dāng)主節(jié)點掛掉時,從節(jié)點自動頂上代替主節(jié)點简识,這樣就可以有效的避免一個節(jié)點掛掉導(dǎo)致整個系統(tǒng)掛掉的問題赶掖,實現(xiàn) redis 服務(wù)的高可用。如下圖:

master-slaver

但是這個方案需要解決兩個基本問題:

  1. 如何提前判斷各個節(jié)點(尤其是主節(jié)點)的運行健康狀況七扰?
  2. 當(dāng)主節(jié)點宕機的時候如何從多個從節(jié)點中選出一個作為新的主節(jié)點并實現(xiàn)自動切換奢赂?

這時 Redis Sentinel 應(yīng)運而生,它主要有以下三個特點:

  • 監(jiān)控(Monitoring):Sentinel 會不斷地檢查你的主服務(wù)器和從服務(wù)器是否運作正常颈走。
  • 提醒(Notification):當(dāng)被監(jiān)控的某個 Redis 服務(wù)器出現(xiàn)問題時呈驶,Sentinel 可以通過 API 向管理員或者其他應(yīng)用程序發(fā)送通知。
  • 自動故障遷移(Automatic failover):當(dāng)一個主服務(wù)器不能正常工作時疫鹊,Sentinel 會開始一次自動故障遷移操作袖瞻, 它會將失效主服務(wù)器的其中一個從服務(wù)器升級為新的主服務(wù)器,并讓失效主服務(wù)器的其他從服務(wù)器改為復(fù)制新的主服務(wù)器拆吆; 當(dāng)客戶端試圖連接失效的主服務(wù)器時聋迎, 集群也會向客戶端返回新主服務(wù)器的地址,使得集群可以使用新主服務(wù)器代替失效服務(wù)器枣耀。

總結(jié)來說就是 sentinel 可以監(jiān)控一個或者多個 master-slaver 集群霉晕,定時對每個節(jié)點進(jìn)行健康檢查,可以通過 API 發(fā)送通知捞奕,并自動進(jìn)行故障轉(zhuǎn)移牺堰。這時r redis 結(jié)構(gòu)就變成了

使用了 redis sentinel 之后客戶端不再直接連接 redis 節(jié)點獲取服務(wù),而是使用 sentinel 代理獲取 redis 服務(wù)颅围,類似 Nginx 的代理模式伟葫。那么這里又有一個新問題,就是如果 sentinel 宕機了院促,那么客戶端就找不到 redis 服務(wù)了筏养,所以 sentinel 本身也是需要支持高可用。

好在sentinel 本身也支持集群部署常拓,并且各個 sentinel 之間支持自動監(jiān)控渐溶,如此一來 redis 主從服務(wù)和 sentinel 服務(wù)都可以支持高可用。預(yù)期結(jié)構(gòu)如下:

redis sentinel集群

部署實例

master-slaver 一主二從

那么下面我們就來實操一下弄抬,以下過程大部分參考 redis 官方 Redis Sentinel 文檔茎辐。

安裝 redis 就不重復(fù)了,和單機 redis 一樣。

redis 解壓后拖陆,redis home 目錄下有 redis 配置的樣例文件弛槐,我們不直接在此文件上就行修改,在redis home目錄下新建文件夾 master-slave 慕蔚,將配置文件都放于此目錄下,下面是三個 redis 節(jié)點配置的關(guān)鍵部分

  • master 配置文件:redis-6379.conf

    port 6379
    daemonize yes
    logfile "6379.log"
    dbfilename "dump-6379.rdb"
    dir "/opt/soft/redis/data"
    
  • slave-1 配置文件:redis-6380.conf

    port 6380
    daemonize yes
    logfile "6380.log"
    dbfilename "dump-6380.rdb"
    dir "/opt/soft/redis/data"
    # 關(guān)鍵配置:將這個 redis 指定為某個第一個 redis 的 slaver
    slaveof 127.0.0.1 6379
    
  • slave-2 配置文件:redis-6381.conf

    port 6381
    daemonize yes
    logfile "6381.log"
    dbfilename "dump-6381.rdb"
    dir "/opt/soft/redis/data"
    # 關(guān)鍵配置:將這個 redis 指定為某個第一個 redis 的 slaver
    slaveof 127.0.0.1 6379
    

分別啟動這三個 redis 服務(wù)斋配,啟動過程就不羅嗦了孔飒,和分別啟動三個單機 redis 是一樣的,分別指定三個配置文件即可艰争。啟動后如下圖所示:

image

6379坏瞄、6380、6381 端口分別在運行一個 redis-server甩卓。

接下來查看這三個 redis-server 之間的關(guān)系:連接到主 redis 上用 info replication即可查看

image

可以看到當(dāng)前連接的 redis 服務(wù)為 master 角色鸠匀,下面有兩個 slaver,IP 和端口都能看到逾柿。

這樣我們就順利的完成了 一主二從 redis 環(huán)境的搭建缀棍,下面開始搭建 sentinel 集群。

sentinel 集群

sentinel 本質(zhì)上是一個特殊的 redis机错,大部分配置和普通的 redis 沒有什么區(qū)別爬范,主要區(qū)別在于端口和其哨兵監(jiān)控設(shè)置,下面是三個典型的 sentinel 配置文件中的關(guān)鍵內(nèi)容:

  • sentinel-26379.conf
#設(shè)置 sentinel 工作端口
port 26379
#后臺運行 
daemonize yes
#日志文件名稱
logfile "26379.log"
#設(shè)置當(dāng)前 sentinel 監(jiān)控的 redis ip 和 端口
sentinel monitor mymaster 127.0.0.1 6379 2
#設(shè)置判斷 redis 節(jié)點宕機時間
sentinel down-after-milliseconds mymaster 60000
#設(shè)置自動故障轉(zhuǎn)移超時
sentinel failover-timeout mymaster 180000
#設(shè)置同時故障轉(zhuǎn)移個數(shù)
sentinel parallel-syncs mymaster 1
  • sentinel-26380.conf
#設(shè)置 sentinel 工作端口
port 26380
#后臺運行 
daemonize yes
#日志文件名稱
logfile "26380.log"
#設(shè)置當(dāng)前 sentinel 監(jiān)控的 redis ip 和 端口
sentinel monitor mymaster 127.0.0.1 6379 2
#設(shè)置判斷 redis 節(jié)點宕機時間
sentinel down-after-milliseconds mymaster 60000
#設(shè)置自動故障轉(zhuǎn)移超時
sentinel failover-timeout mymaster 180000
#設(shè)置同時故障轉(zhuǎn)移個數(shù)
sentinel parallel-syncs mymaster 1
  • sentinel-26381.conf

    #設(shè)置 sentinel 工作端口
    port 26391
    #后臺運行 
    daemonize yes
    #日志文件名稱
    logfile "26381.log"
    #設(shè)置當(dāng)前 sentinel 監(jiān)控的 redis ip 和 端口
    sentinel monitor mymaster 127.0.0.1 6379 2
    #設(shè)置判斷 redis 節(jié)點宕機時間
    sentinel down-after-milliseconds mymaster 60000
    #設(shè)置自動故障轉(zhuǎn)移超時
    sentinel failover-timeout mymaster 180000
    #設(shè)置同時故障轉(zhuǎn)移個數(shù)
    sentinel parallel-syncs mymaster 1
    

針對幾個監(jiān)控設(shè)置的配置做一下詳細(xì)說明:

  • sentinel monitor [master-group-name] [ip] [port] [quorum]

    這個命令中【master-group-name】是 master redis 的名稱弱匪;【ip】和【port】分別是其 ip 和端口青瀑,很好理解。最后一個參數(shù)【quorum】是”投票數(shù)“

    舉個栗子萧诫,redis 集群中有3個 sentinel 實例斥难,其中 master 掛掉了,如果這里的票數(shù)是2帘饶,表示有2個 sentinel 認(rèn)為 master 掛掉啦哑诊,才能被認(rèn)為是正真的掛掉啦。其中 sentinel 集群中各個 sentinel 之間通過 gossip 協(xié)議互相通信及刻。
    具體怎樣投票還涉及到 redis 集群中的【主觀下線】和【客觀下線】的概念搭儒,后面再詳細(xì)介紹。

    • down-after-milliseconds

      sentinel 會向 master 發(fā)送心跳 PING 來確認(rèn) master 是否存活提茁,如果 master 在“一定時間范圍”內(nèi)不回應(yīng)PONG 或者是回復(fù)了一個錯誤消息淹禾,那么這個 sentinel 會主觀地認(rèn)為這個 master 已經(jīng)不可用了。而這個down-after-milliseconds 就是用來指定這個“一定時間范圍”的茴扁,單位是毫秒铃岔。

    • failover-timeout

      這個參數(shù) redis 官方文檔中并未做詳細(xì)說明,但是很好理解,就是 sentinel 對 redis 節(jié)點進(jìn)行自動故障轉(zhuǎn)移的超時設(shè)置毁习,當(dāng) failover(故障轉(zhuǎn)移)開始后智嚷,在此時間內(nèi)仍然沒有觸發(fā)任何 failover 操作,當(dāng)前sentinel 將會認(rèn)為此次故障轉(zhuǎn)移失敗纺且。

    • parallel-syncs

      當(dāng)新master產(chǎn)生時盏道,同時進(jìn)行 slaveof 到新 master 并進(jìn)行同步復(fù)制的 slave 個數(shù),也就是同時幾個 slave 進(jìn)行同步。因為在 salve 執(zhí)行 salveof 與新 master 同步時载碌,將會終止客戶端請求猜嘱,因此這個值需要權(quán)衡。此值較大嫁艇,意味著“集群”終止客戶端請求的時間總和和較大朗伶,此值較小,意味著“集群”在故障轉(zhuǎn)移期間,多個 salve 向客戶端提供服務(wù)時仍然使用舊數(shù)據(jù)步咪。

      我們配置三個 sentinel 幾點組成一個 sentinel 集群论皆,端口分別是 23679,23680猾漫,23681

然后就可以啟動 sentinel 集群了

啟動 sentinel 有兩種方式:

  1. redis-sentinel /path/to/sentinel.conf
  2. redis-server /path/to/sentinel.conf --sentinel

這兩種啟動方式?jīng)]有區(qū)別点晴,按照順序分別啟動三個 sentinel 節(jié)點之后,我們?nèi)我膺B接其中的一個 sentinel 節(jié)點查看集群關(guān)系悯周,如下圖:


image

我們連接 26379 這個端口的 sentinel觉鼻,用 info sentinel命令可以看到這個 sentinel 監(jiān)控的 master redis 服務(wù)的 ip,端口队橙,以及 maste 的 slaver 節(jié)點數(shù)量坠陈,以及 sentinel 的數(shù)量。

再連接 26380 這個節(jié)點試試:

image

可以看到結(jié)果和上面一樣捐康。

如此仇矾,我們的 sentinel 集群也部署完成了

那么,當(dāng)前這個 redis sentinel 高可用集群的做種拓?fù)鋱D如下:

image

高可用故障測試

下面我們來測試一下這個高可用方案的實際能力解总。

我們手動把一主二從中的主節(jié)點 kill 掉:

image

然后連接 6380 節(jié)點贮匕,查看集群狀態(tài):


image

可以看到 6380 節(jié)點已經(jīng)自動升級為了 master 節(jié)點,還有 6381 這一個 slaver 節(jié)點花枫,自動故障轉(zhuǎn)移成功

我們再手動啟動 6379 節(jié)點刻盐,觀察集群狀態(tài):

image

如圖,6379節(jié)點重新啟動后劳翰,自動變成了 6380 節(jié)點的從節(jié)點敦锌。

如此一套完整的 redis 高可用方案就部署完成了。

Redis 主觀下線和客觀下線

前面說過佳簸, Redis 的 Sentinel 中關(guān)于下線(down)有兩個不同的概念:

  • 主觀下線(Subjectively Down乙墙, 簡稱 SDOWN)指的是單個 Sentinel 實例對服務(wù)器做出的下線判斷。
  • 客觀下線(Objectively Down, 簡稱 ODOWN)指的是多個 Sentinel 實例在對同一個服務(wù)器做出 SDOWN 判斷听想, 并且通過 SENTINEL is-master-down-by-addr 命令互相交流之后腥刹, 得出的服務(wù)器下線判斷。 (一個 Sentinel 可以通過向另一個 Sentinel 發(fā)送 SENTINEL is-master-down-by-addr 命令來詢問對方是否認(rèn)為給定的服務(wù)器已下線)

如果一個服務(wù)器沒有在 master-down-after-milliseconds 選項所指定的時間內(nèi)汉买, 對向它發(fā)送 PING 命令的 Sentinel 返回一個有效回復(fù)(valid reply)衔峰, 那么 Sentinel 就會將這個服務(wù)器標(biāo)記為主觀下線。

服務(wù)器對 PING 命令的有效回復(fù)可以是以下三種回復(fù)的其中一種:

  • 返回 +PONG 蛙粘。
  • 返回 -LOADING 錯誤垫卤。
  • 返回 -MASTERDOWN 錯誤。

如果服務(wù)器返回除以上三種回復(fù)之外的其他回復(fù)组题, 又或者在指定時間內(nèi)沒有回復(fù) PING 命令葫男, 那么 Sentinel 認(rèn)為服務(wù)器返回的回復(fù)無效(non-valid)抱冷。

注意崔列, 一個服務(wù)器必須在 master-down-after-milliseconds 毫秒內(nèi), 一直返回?zé)o效回復(fù)才會被 Sentinel 標(biāo)記為主觀下線旺遮。

舉個栗子赵讯, 如果 master-down-after-milliseconds 選項的值為 30000 毫秒(30 秒), 那么只要服務(wù)器能在每 29 秒之內(nèi)返回至少一次有效回復(fù)耿眉, 這個服務(wù)器就仍然會被認(rèn)為是處于正常狀態(tài)的边翼。

從主觀下線狀態(tài)切換到客觀下線狀態(tài)并沒有使用嚴(yán)格的法定人數(shù)算法(strong quorum algorithm), 而是使用了流言協(xié)議: 如果 Sentinel 在給定的時間范圍內(nèi)鸣剪, 從其他 Sentinel 那里接收到了足夠數(shù)量的主服務(wù)器下線報告组底, 那么 Sentinel 就會將主服務(wù)器的狀態(tài)從主觀下線改變?yōu)榭陀^下線。 如果之后其他 Sentinel 不再報告主服務(wù)器已下線筐骇, 那么客觀下線狀態(tài)就會被移除债鸡。

有一點需要注意的是:客觀下線條件只適用于主服務(wù)器: 對于任何其他類型的 Redis 實例, Sentinel 在將它們判斷為下線前不需要進(jìn)行協(xié)商铛纬, 所以從服務(wù)器或者其他 Sentinel 永遠(yuǎn)不會達(dá)到客觀下線條件厌均。

只要一個 Sentinel 發(fā)現(xiàn)某個主服務(wù)器進(jìn)入了客觀下線狀態(tài), 這個 Sentinel 就可能會被其他 Sentinel 推選出告唆, 并對失效的主服務(wù)器執(zhí)行自動故障遷移操作棺弊。

Redis 分布式高可用方案:Redis Cluster

原理簡介

作為一個內(nèi)存數(shù)據(jù)庫,實現(xiàn)高可用是一個基本保障擒悬,當(dāng)儲存服務(wù)在可預(yù)見的將來需要做存儲拓展時模她,分布式儲存就是一個必須要考慮到的事情。例如部署一個中央 redis 儲存服務(wù)懂牧,提供給集團(tuán)下所有的子公司所有需要的系統(tǒng)使用缝驳,并且系統(tǒng)數(shù)量在不斷的增加,此時在部署服務(wù)的時候,分布式儲存結(jié)構(gòu)幾乎是必然的選擇用狱。

Redis 3.0 版本之前运怖,可以通過前面說所的 Redis Sentinel(哨兵)來實現(xiàn)高可用 ( HA ),從 3.0 版本之后夏伊,官方推出了Redis Cluster摇展,它的主要用途是實現(xiàn)數(shù)據(jù)分片(Data Sharding),同時提供了完整的 sharding溺忧、replication(復(fù)制機制仍使用原有機制咏连,并且具備感知主備的能力)、failover 解決方案鲁森,稱為 Redis Cluster祟滴,同樣可以實現(xiàn) HA,是官方當(dāng)前推薦的方案歌溉。

在 Redis Sentinel 模式中垄懂,每個節(jié)點需要保存全量數(shù)據(jù),冗余比較多痛垛,而在Redis Cluster 模式中草慧,每個分片只需要保存一部分的數(shù)據(jù),對于內(nèi)存數(shù)據(jù)庫來說匙头,還是要盡量的減少冗余漫谷。在數(shù)據(jù)量太大的情況下,故障恢復(fù)需要較長時間蹂析,另外舔示,內(nèi)存的價格也是非常高昂的。

Redis Cluste r的具體實現(xiàn)細(xì)節(jié)是采用了 Hash 槽的概念电抚,集群會預(yù)先分配16384個槽(slot)惕稻,并將這些槽分配給具體的服務(wù)節(jié)點,通過對 Key 進(jìn)行 CRC16(key)%16384 運算得到對應(yīng)的槽是哪一個喻频,從而將讀寫操作轉(zhuǎn)發(fā)到該槽所對應(yīng)的服務(wù)節(jié)點缩宜。當(dāng)有新的節(jié)點加入或者移除的時候,再來遷移這些槽以及其對應(yīng)的數(shù)據(jù)甥温。在這種設(shè)計之下锻煌,我們就可以很方便的進(jìn)行動態(tài)擴(kuò)容或縮容。

當(dāng)然姻蚓,關(guān)于高可用的實現(xiàn)方案宋梧,也可以將 Redis-Sentinel 和 Redis-Cluster 兩種模式結(jié)合起來使用,不過比較復(fù)雜狰挡,并不太推薦捂龄。

下圖展示了 Redis Cluster 分配 key 和 slot 的基本原理:

redis cluster原理圖

一個典型的 Redis Cluster 分布式集群由多個Redis節(jié)點組成释涛。不同的節(jié)點組服務(wù)的數(shù)據(jù)無交集,每個節(jié)點對應(yīng)數(shù)據(jù) sharding 的一個分片倦沧。節(jié)點組內(nèi)部分為主備 2 類唇撬,對應(yīng)前面敘述的 master 和 slave。兩者數(shù)據(jù)準(zhǔn)實時一致展融,通過異步化的主備復(fù)制機制保證窖认。一個節(jié)點組有且僅有一個 master,同時有0到多個 slave告希。只有 master 對外提供寫服務(wù)扑浸,讀服務(wù)可由 master/slave 提供。如下所示:

Redis Cluster 拓?fù)浣Y(jié)構(gòu)

上圖中燕偶,key-value 全集被分成了 5 份喝噪,5個 slot(實際上Redis Cluster有 16384 [0-16383] 個slot,每個節(jié)點服務(wù)一段區(qū)間的slot指么,這里面僅僅舉例)酝惧。A和B為master節(jié)點,對外提供寫服務(wù)涧尿。分別負(fù)責(zé) 1/2/3 和 4/5 的slot系奉。A/A1 和B/B1/B2 之間通過主備復(fù)制的方式同步數(shù)據(jù)檬贰。

上述的5個節(jié)點姑廉,兩兩通過 Redis Cluster Bus 交互,相互交換如下的信息:

1翁涤、數(shù)據(jù)分片(slot)和節(jié)點的對應(yīng)關(guān)系桥言;

2、集群中每個節(jié)點可用狀態(tài)葵礼;

3号阿、集群結(jié)構(gòu)發(fā)生變更時,通過一定的協(xié)議對配置信息達(dá)成一致鸳粉。數(shù)據(jù)分片的遷移扔涧、主備切換、單點 master 的發(fā)現(xiàn)和其發(fā)生主備關(guān)系變更等届谈,都會導(dǎo)致集群結(jié)構(gòu)變化枯夜。

4、publish/subscribe(發(fā)布訂閱)功能艰山,在Cluster版內(nèi)部實現(xiàn)所需要交互的信息湖雹。

Redis Cluster Bus 通過單獨的端口進(jìn)行連接,由于Bus是節(jié)點間的內(nèi)部通信機制曙搬,交互的是字節(jié)序列化信息摔吏。相對 Client 的字符序列化來說鸽嫂,效率較高。

Redis Cluster是一個去中心化的分布式實現(xiàn)方案征讲,客戶端和集群中任一節(jié)點連接据某,然后通過后面的交互流程,逐漸的得到全局的數(shù)據(jù)分片映射關(guān)系诗箍。

更多更詳細(xì)的 redis cluster 的說明請移步Redis Cluster 官方文檔

部署實例

Redis Cluster 集群至少需要三個 master 節(jié)點哗脖,本文將以單機多實例的方式部署3個主節(jié)點及3個從節(jié)點,6個節(jié)點實例分別使用不同的端口及工作目錄

安裝 redis 同上扳还,不贅述才避。

  1. 為每個 redis 節(jié)點分別創(chuàng)建工作目錄

    在redis安裝目錄 /usr/local/redis-5.0.2 下新建目錄 redis-cluster,并在該目錄下再新建6個子目錄氨距,7000,7001,8000,8001,9000,9001桑逝,此時目錄結(jié)構(gòu)如下圖所示:

image
  1. 修改配置

    #開啟后臺運行
    daemonize yes
    #工作端口
    port 7000
    #綁定機器的內(nèi)網(wǎng)IP或者公網(wǎng)IP,一定要設(shè)置,不要用 127.0.0.1
    bind 172.27.0.8  
    #指定工作目錄俏让,rdb,aof持久化文件將會放在該目錄下楞遏,不同實例一定要配置不同的工作目錄
    dir /usr/local/redis-cluster/7000/
    #啟用集群模式
    cluster-enabled yes 
    #生成的集群配置文件名稱,集群搭建成功后會自動生成首昔,在工作目錄下
    cluster-config-file nodes-7000.conf 
    #節(jié)點宕機發(fā)現(xiàn)時間寡喝,可以理解為主節(jié)點宕機后從節(jié)點升級為主節(jié)點時間
    cluster-node-timeout 5000 
    #開啟AOF模式
    appendonly yes 
    #pid file所在目錄
    pidfile /var/run/redis_8001.pid 
    
  2. 按照上面的樣例將配置文件復(fù)制到另外5個目錄下,并對 port勒奇、dir预鬓、cluster-config-file 三個屬性做對應(yīng)修改,這里就不一一列舉了赊颠。

  3. 安裝 Ruby 和 RubyGems

    由于創(chuàng)建 redis cluster 需要用到 redis-trib 命令格二,而這個命令依賴 Ruby 和 RubyGems,因此需要安裝一下竣蹦。

    [root@VM_0_15_centos redis-cluster]# yum install ruby
    [root@VM_0_15_centos redis-cluster]# yum install rubygems
    [root@VM_0_15_centos redis-cluster]# gem install redis --version 3.3.3
    
  4. 分別啟動6個節(jié)點

    [root@VM_0_15_centos redis-4.0.6]# ./src/redis-server redis-cluster/7000/redis.conf
    [root@VM_0_15_centos redis-4.0.6]# ./src/redis-server redis-cluster/7001/redis.conf
    [root@VM_0_15_centos redis-4.0.6]# ./src/redis-server redis-cluster/8000/redis.conf
    [root@VM_0_15_centos redis-4.0.6]# ./src/redis-server redis-cluster/8001/redis.conf
    [root@VM_0_15_centos redis-4.0.6]# ./src/redis-server redis-cluster/9000/redis.conf
    [root@VM_0_15_centos redis-4.0.6]# ./src/redis-server redis-cluster/9001/redis.conf
    
  5. 查看服務(wù)運行狀態(tài)

    [root@VM_0_15_centos redis-4.0.6]# ps -ef | grep redis
    root     20290     1  0 18:33 ?        00:00:02 ./src/redis-server *:8001 [cluster]
    root     20295     1  0 18:33 ?        00:00:02 ./src/redis-server *:8002 [cluster]
    root     20300     1  0 18:33 ?        00:00:02 ./src/redis-server *:8003 [cluster]
    root     20305     1  0 18:33 ?        00:00:02 ./src/redis-server *:8004 [cluster]
    root     20310     1  0 18:33 ?        00:00:02 ./src/redis-server *:8005 [cluster]
    root     20312     1  0 18:33 ?        00:00:02 ./src/redis-server *:8006 [cluster]
    root     22913 15679  0 19:31 pts/2    00:00:00 grep --color=auto redis
    

    可以看到6個節(jié)點以及全部成功啟動

  6. 創(chuàng)建 redis cluster

    [root@VM_0_15_centos redis-4.0.6]# ./src/redis-trib.rb create --replicas 1 172.27.0.8:7000 172.27.0.8:7001 172.27.0.8:8000 172.27.0.8:8001 172.27.0.8:9000 172.27.0.8:90001
    

    創(chuàng)建過程中會有部分需要確認(rèn)的地方顶猜,按照提示輸入即可,集群創(chuàng)建完畢后觀察一下這個集群的節(jié)點狀態(tài)

    172.27.0.8:7000> cluster nodes
    068ac2afe1ade8b69b83226453fecc2b79cd93ae 172.27.0.8:7001@17001 slave 421ebe9e0a5ac6c811935ecd9dba83ef119dec17 0 1531008204920 4 connected
    784c727c83a5952d3714ac211021f909cc4dfee4 172.27.0.8:8001@18001 slave eb5d700e2f030c02fb1f30ba4420d0b4f7170d84 0 1531008203000 5 connected
    0537099e7cc7ab595c7aad5f0c96985251b85ec0 172.27.0.8:9001@19001 slave 79262341417df0a11eaf31e72bbf3e26f5f60ebf 0 1531008204419 6 connected
    421ebe9e0a5ac6c811935ecd9dba83ef119dec17 172.27.0.8:7000@17000 myself,master - 0 1531008204000 1 connected 0-5460
    eb5d700e2f030c02fb1f30ba4420d0b4f7170d84 172.27.0.8:8000@18000 master - 0 1531008203000 2 connected 5461-10922
    79262341417df0a11eaf31e72bbf3e26f5f60ebf 172.27.0.8:9000@19000 master - 0 1531008203419 3 connected 10923-16383
    

    如上所示痘括,一個 3主3從的 redis cluster 分布式集群就搭建成功了长窄,7000、8000纲菌、9000分別是三個 master 節(jié)點挠日,7001、8001和9001為對應(yīng)的 slaver 節(jié)點驰后。

其實如果你并不想管這么多配置而只是想在最快的速度內(nèi)創(chuàng)建一個 redis cluster 用作測試或者其他用途肆资, redis 官方在 redis 安裝目錄的 Utils 目錄下提供了一個 create-cluster 的腳本,如下圖:

image

只要執(zhí)行一下這個腳本就能自動創(chuàng)建一個 cluster:

[圖片上傳失敗...(image-c6eea0-1554881540128)]

進(jìn)入到這個目錄下灶芝,執(zhí)行./create-cluster start郑原,即可立即完成一個 三主三從的 redis-cluster 的搭建:

image

如下圖所示就是直接使用這個腳本創(chuàng)建的 redis cluster:

image

Tips

  1. 如果想重新創(chuàng)建集群唉韭,需要登錄到每個節(jié)點,執(zhí)行 flushdb犯犁,然后執(zhí)行cluster reset,重啟節(jié)點酸役;

  2. 如果要批量殺掉Redis進(jìn)程,可以使用 pkill redis-server命令贱呐;

  3. 如果redis開啟了密碼認(rèn)證,則需要在redis.conf中增加屬性 : masterauth yourpassword 入桂,并且需要修改/usr/local/share/gems/gems/redis-3.3.3/lib/redis目錄下的client.rb文件奄薇,將password屬性設(shè)置為redis.conf中的requirepass的值馁蒂,不同的操作系統(tǒng)client.rb的位置可能不一樣,可以使用 find / -name "client.rb"全盤查找一下蜘腌;

 DEFAULTS = {
      :url => lambda { ENV["REDIS_URL"] },
      :scheme => "redis",
      :host => "127.0.0.1",
      :port => 6379,
      :path => nil,
      :timeout => 5.0,
      :password => "yourpassword",
      :db => 0,
      :driver => nil,
      :id => nil,
      :tcp_keepalive => 0,
      :reconnect_attempts => 1,
      :inherit_socket => false
    }
  1. Redis開啟密碼認(rèn)證后沫屡,在集群操作時問題會比較多撮珠,因此在非特殊情況下不建議開啟密碼認(rèn)證,可以搭配使用防火墻保證 Redis 的安全劫瞳。

故障測試的方法與上面一樣志于,故不贅述废睦。

總結(jié)

Redis 服務(wù)的部署方案的選型大家根據(jù)自己項目的需求部署即可,一般來說 redis sentinel 就夠用了奈应,也是目前用得最多的模式购披,但是 redis 3.0 之后官方推出的 redis-cluster 雖然本質(zhì)是用于實現(xiàn)數(shù)據(jù)分片和分布式存儲,但是其也實現(xiàn)了 redis sentinel 的全部功能惩妇,有完全的 HA 能力,并且部署起來更簡單歌殃,因此成為了官方推薦的 HA 方案氓皱。我個人也更加推薦 redis cluster 方案。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末股淡,一起剝皮案震驚了整個濱河市廷区,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌早敬,老刑警劉巖大脉,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件镰矿,死亡現(xiàn)場離奇詭異,居然都是意外死亡绝淡,警方通過查閱死者的電腦和手機苍姜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來馍乙,“玉大人垫释,你說我怎么就攤上這事∠则颍” “怎么了订咸?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長涩禀。 經(jīng)常有香客問我艾船,道長,這世上最難降的妖魔是什么屿岂? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任爷怀,我火速辦了婚禮,結(jié)果婚禮上烤惊,老公的妹妹穿的比我還像新娘吁朦。我一直安慰自己,他們只是感情好雄右,可當(dāng)我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布擂仍。 她就那樣靜靜地躺著熬甚,像睡著了一般。 火紅的嫁衣襯著肌膚如雪复局。 梳的紋絲不亂的頭發(fā)上粟判,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天峦剔,我揣著相機與錄音吝沫,去河邊找鬼递礼。 笑死始花,一個胖子當(dāng)著我的面吹牛曼追,可吹牛的內(nèi)容都是我干的将硝。 我是一名探鬼主播依疼,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼而芥,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了误辑?” 一聲冷哼從身側(cè)響起歌逢,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤趋翻,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后师骗,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體讨惩,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年黍少,在試婚紗的時候發(fā)現(xiàn)自己被綠了厂置。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片魂角。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖访忿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情迹恐,我是刑警寧澤卧斟,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布唆涝,位于F島的核電站,受9級特大地震影響能耻,放射性物質(zhì)發(fā)生泄漏亡驰。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一戒职、第九天 我趴在偏房一處隱蔽的房頂上張望透乾。 院中可真熱鬧乳乌,春花似錦、人聲如沸汉操。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽针炉。三九已至仰担,卻和暖如春绩社,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背贮尉。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工猜谚, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人昌犹。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓览芳,卻偏偏與公主長得像,于是被迫代替她去往敵國和親铸敏。 傳聞我的和親對象是個殘疾皇子悟泵,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 本文是對Redis的集群部署模式一個學(xué)習(xí)總結(jié)糕非,共包括如下章節(jié)內(nèi)容: 概述 主從集群模式 “哨兵”集群模式 Clus...
    我是老薛閱讀 941評論 0 4
  • 因為Redis擁有諸多優(yōu)秀的特性朽肥,使用范圍越來越廣,系統(tǒng)對其可用性的依賴也越來越重融师,當(dāng)前絕大部分系統(tǒng)使用的Redi...
    十毛tenmao閱讀 414評論 0 1
  • 一篇好的軟文和游戲文案能帶來什么效果怀伦,你知道嗎山林?作為一個游戲運營及資深游戲玩家的我來說,入的許多游戲的坑都是因為某...
    牧野在冊閱讀 15,504評論 0 7
  • “有一種冷是你媽覺得你冷”绣硝,到底怎么給寶寶穿衣才是最科學(xué)的呢?怎么判斷寶寶冷不冷鹉胖? 上一輩的穿衣經(jīng):能穿多少穿多少...
    孩子怎么教閱讀 191評論 0 0
  • 在互聯(lián)網(wǎng)時代次员,越來越多的企業(yè)開始要求,原來分割的產(chǎn)品市殷、營銷和渠道刹衫,不僅要各司其職,更要實現(xiàn)融合音羞。我們簡稱:營銷一體...
    Jinyuba閱讀 399評論 0 0