本文是對Redis的集群部署模式一個學習總結(jié)膀懈,共包括如下章節(jié)內(nèi)容:
- 概述
- 主從集群模式
- “哨兵”集群模式
- Cluster集群模式
- 小結(jié)
參考資料:
1赌莺、如果需要對Redis的基本知識有所了解,可參考《Redis學習筆記1-基礎(chǔ)知識》
揣非,本文中涉及到redis運行環(huán)境是基于這篇文章介紹的趟径。
一、概述
Redis提供了單機模式的服務(wù),但在實際的生產(chǎn)環(huán)境下绍豁,單機模式往往無法滿足需求芯咧,一般需要集群模式。
Redis有三種集群模式竹揍,分別是:
主從集群模式
“哨兵”模式
Cluster集群模式
其中第三種的集群模式是在Redis 3.x以后的版本才增加進來的敬飒,也正是因為有這個功能,Redis才真正成為一個分布式的數(shù)據(jù)庫系統(tǒng)芬位。
下面我們來分別介紹這三種模式无拗。
二、主從集群模式
(一)基本概念
Redis的主從集群模式昧碉,類似傳統(tǒng)的主從數(shù)據(jù)庫方式英染。在該模式下,可以有一個主數(shù)據(jù)庫(master)節(jié)點被饿,多個從數(shù)據(jù)庫(slave)節(jié)點四康。主數(shù)據(jù)庫可以進行讀寫操作,當寫操作導(dǎo)致數(shù)據(jù)變化時會自動將數(shù)據(jù)同步給從數(shù)據(jù)庫狭握。而從數(shù)據(jù)庫一般是只讀的闪金,并接受主數(shù)據(jù)庫同步過來的數(shù)據(jù)。一個主數(shù)據(jù)庫可以擁有多個從數(shù)據(jù)庫,而一個從數(shù)據(jù)庫只能擁有一個主數(shù)據(jù)庫哎垦。
(二)配置
主節(jié)點不需要做特殊的配置囱嫩。
從節(jié)點需要在配置文件redis.conf中增加一項配置,如下:
slaveof master_ip master_port
注意漏设,上面的master_ip和master_portip指的是主節(jié)點的ip和port墨闲,顯然這個配置信息的作用是讓從節(jié)點可以找到主節(jié)點。
在測試環(huán)境下愿题,也可以不在配置文件中配置损俭,而是在啟動從服務(wù)器時通過參數(shù)指定,如:
src/redis-server --slaveof master_ip master_port
(三)復(fù)制機制
Slave啟動后潘酗,會連接到Master杆兵,連接之后,它將主動發(fā)送一個SYNC命令仔夺。Master收到同步命令后將啟動后臺存盤進程琐脏,同時收集所有接收到的用于修改數(shù)據(jù)集的命令,在后臺進程執(zhí)行完畢后缸兔,Master將傳送整個數(shù)據(jù)庫文件到Slave日裙,以完成一次完全同步。而Slave在接收到數(shù)據(jù)庫文件數(shù)據(jù)之后將其存盤并加載到內(nèi)存中惰蜜。
此后昂拂,Master繼續(xù)將所有已經(jīng)收集到的修改命令,和新的修改命令依次傳送給Slaves抛猖,Slave將在本次執(zhí)行這些數(shù)據(jù)修改命令格侯,從而達到最終的數(shù)據(jù)同步。 如果Master和Slave之間的鏈接出現(xiàn)斷連現(xiàn)象财著,Slave可以自動重連Master联四,但是在連接成功之后,一次完全同步將被自動執(zhí)行撑教。
(四)主從模式的作用
Redis主從集群模式的作用主要有如下兩點
1朝墩、數(shù)據(jù)備份保護:當一個節(jié)點數(shù)據(jù)損壞(物理損壞),因為有備份的節(jié)點伟姐,所以數(shù)據(jù)可以恢復(fù)收苏。
2、負載均衡:所有客戶端都訪問一個節(jié)點肯定會影響Redis工作效率愤兵,有了主從以后倒戏,查詢操作就可以通過查詢從節(jié)點來完成。
(五)主從模式的特點
Redis主從集群模式的主要有如下特點:
1恐似、一個Master可以有多個Slave杜跷,默認配置下,master節(jié)點可以進行讀和寫,slave節(jié)點只能進行讀操作葛闷,寫操作被禁止憋槐。不要修改配置讓slave節(jié)點支持寫操作,這沒有意義淑趾,原因一阳仔,寫入的數(shù)據(jù)不會被同步到其他節(jié)點;原因二扣泊,當master節(jié)點修改同一條數(shù)據(jù)后近范,slave節(jié)點的數(shù)據(jù)會被覆蓋掉。
2延蟹、slave節(jié)點掛了不影響其他slave節(jié)點的讀和master節(jié)點的讀和寫评矩,重新啟動后會將數(shù)據(jù)從master節(jié)點同步過來。
3阱飘、master節(jié)點掛了以后斥杜,不影響slave節(jié)點的讀,但Redis不會自動從slave節(jié)點選一個master沥匈,這樣將不再提供寫服務(wù)蔗喂,這是個很大的問題,因為這時集群相當于無法提供服務(wù)了高帖。要想自動將slave轉(zhuǎn)為master缰儿,需要采用“哨兵”集群模式,這個在下面介紹散址。
三乖阵、"哨兵"集群模式
(一)基本概念
上面介紹了Redis的主從集群模式,該模式最大的問題一旦master出問題爪飘,整個集群將無法提供寫的服務(wù)义起,且不能自動將slave切換為master拉背。所以在實際生產(chǎn)環(huán)境中师崎,主從模式是不太常用的。
因此Redis官方提供了“哨兵”(Sentinel)集群模式椅棺,Sentinel模式犁罩,顧名思義,就是有一個Sentinel系統(tǒng)两疚,來監(jiān)控Redis集群的運行狀態(tài)床估,并根據(jù)情況觸發(fā)相應(yīng)的動作。Redis Sentinel作為Redis官方提供的集群管理工具诱渤,主要有如下功能:
1丐巫、監(jiān)控:能持續(xù)監(jiān)控Redis的主從實例是否正常工作;
2、通知:當被監(jiān)控的Redis實例出問題時递胧,能通過API通知系統(tǒng)管理員或其他程序碑韵;
3、自動故障恢復(fù):如果主實例無法正常工作缎脾,Sentinel將啟動故障恢復(fù)機制把一個從實例提升為主實例祝闻,其他的從實例將會被重新配置到新的主實例,且應(yīng)用程序會得到一個更換新地址的通知遗菠。
4联喘、配置提供:因為sentinel保存著Redis主從的信息,所以Redis可以從sentinel那獲得所有的配置信息辙纬。
Redis Sentinel本身也可以配置成一個集群系統(tǒng)豁遭,可以部署多個Sentinel實例來監(jiān)控同一組Redis實例,當然只有一個Sentinel實例也qiehuanwei可以完成上面的功能牲平,只是一個sentinel實例不具備高可用性堤框,所以一般也會搭建sentinel集群。
雖然sentinel物理上對應(yīng)的是一個獨立的可執(zhí)行文件纵柿,文件名是redis-sentinel蜈抓,但實質(zhì)上它只是一個運行在特殊模式下的 Redis 服務(wù)器, 也可以在啟動一個普通 Redis 服務(wù)器時通過給定 --sentinel 選項來啟動 Redis Sentinel昂儒。
(二)配置
sentinel服務(wù)與redis服務(wù)一樣沟使,也有一個配置文件,配置文件名叫sentinel.conf渊跋,與redis服務(wù)的redis.conf配置文件都位于redis的根目錄下腊嗡。
啟動 Sentinel 實例必須指定相應(yīng)的配置文件, 系統(tǒng)會使用配置文件來保存 Sentinel 的當前狀態(tài)拾酝, 并在 Sentinel 重啟時通過載入配置文件來進行狀態(tài)還原燕少。如果啟動 Sentinel 時沒有指定相應(yīng)的配置文件, 或者指定的配置文件不可寫(not writable)蒿囤, 那么 Sentinel 會拒絕啟動客们。我們需要在sentinel.conf配置文件中配置要監(jiān)聽的redis主節(jié)點等信息,關(guān)于如何配置材诽,這里不再詳細介紹底挫。配置好配置文件后,就可以啟動sentinel服務(wù)了脸侥,啟動方式如下:
src/redis-sentinel sentinel.conf
或者
src/redis-server sentinel.conf --sentinel
上面兩種方式建邓,都將啟動一個sentinel實例。
(三)“哨兵”模式的特點
相比主從模式中睁枕,sentinel模式最大的特點是:當sentinel發(fā)現(xiàn)master節(jié)點掛了以后官边,sentinel就會從slave中重新選舉一個master沸手,這樣保證Redis集群可持續(xù)的提供服務(wù)。
下面是對sentinel模式的一些特點的具體說明注簿。
1罐氨、sentinel模式是建立在主從模式的基礎(chǔ)上的,如果只有一個Redis節(jié)點滩援,sentinel就沒有任何意義栅隐。
2、當master節(jié)點掛了以后玩徊,sentinel會在slave中選擇一個做為master租悄,并修改它們的配置文件,其他slave的配置文件也會被修改恩袱,比如slaveof屬性會指向新的master泣棋。
3、當master節(jié)點重新啟動后畔塔,它將不再是master潭辈,而是做為slave接收新的master節(jié)點的同步數(shù)據(jù)。
4澈吨、sentinel因為也是一個進程有掛掉的可能把敢,所以sentinel也可以啟動多個形成一個sentinel集群。
5谅辣、一個sentinel或sentinel集群可以管理多個主從Redis修赞。
6、sentinel最好不要和Redis部署在同一臺機器桑阶,不然Redis的服務(wù)器掛了以后柏副,sentinel也掛了。
7蚣录、sentinel監(jiān)控的Redis集群都會定義一個master名字割择,這個名字代表Redis集群的master Redis。
8萎河、當使用sentinel模式的時候荔泳,客戶端就不要直接連接Redis,而是連接sentinel的ip和port公壤,由sentinel來提供具體的可提供服務(wù)的Redis實現(xiàn)换可,這樣當master節(jié)點掛掉以后椎椰,sentinel就會感知并將新的master節(jié)點提供給使用者厦幅。
sentinel模式基本可以滿足一般生產(chǎn)的需求,具備高可用性慨飘。但是當數(shù)據(jù)量過大到一臺服務(wù)器存放不下的情況時(因為不管是主從模式确憨、還是sentinel模式译荞,主節(jié)點上都存儲了所有數(shù)據(jù)),這時主從模式或sentinel模式就不能滿足需求了休弃,就需要對存儲的數(shù)據(jù)進行分片吞歼,將數(shù)據(jù)存儲到多個Redis實例中,這就是下面要講的cluster集群模式塔猾,即Redis真正的分布式集群系統(tǒng)篙骡。
四、Cluster集群模式
(一)基本概念
cluster模式是為了解決單機Redis容量有限的問題丈甸,同時也能提高存取速度糯俗。Redis-Cluster采用無中心結(jié)構(gòu),每個節(jié)點都保存數(shù)據(jù)和整個集群狀態(tài),每個節(jié)點都和其他所有節(jié)點連接睦擂。其架構(gòu)圖如下:
雖然在cluster模式下得湘,各個結(jié)點是互聯(lián)并且功能等同的,但實際上結(jié)點還是分為master和slave兩種顿仇。一個cluster集群需要多個master節(jié)點淘正,每個master節(jié)點對應(yīng)一個或多個slave節(jié)點。同主從模式和“哨兵”模式一樣臼闻,master節(jié)點可寫可讀鸿吆,slave節(jié)點只能讀,一旦master出問題述呐,會讓slave自動成為master伞剑。客戶端寫數(shù)據(jù)時市埋,會根據(jù)一定的機制將數(shù)據(jù)寫到不同的master上黎泣,并從該master復(fù)制到對應(yīng)的slave節(jié)點上。
(二)集群機制
Redis 集群使用數(shù)據(jù)分片(sharding)而非一致性哈希(consistency hashing)來決定數(shù)據(jù)的寫入缤谎。一個 Redis cluster集群包含 16384 個哈希槽(hash slot)抒倚。集群中的每個主節(jié)點負責處理一部分哈希槽。 舉個例子坷澡, 如果集群有三個主節(jié)點A,B,C托呕, 會這樣分配:
1、節(jié)點 A 負責處理 0 號至 5500 號哈希槽频敛。
2项郊、節(jié)點 B 負責處理 5501 號至 11000 號哈希槽。
3斟赚、節(jié)點 C 負責處理 11001 號至 16384 號哈希槽着降。
客戶端寫入的數(shù)據(jù)(鍵值對)中的鍵會按照一定的算法來確定這個鍵屬于這16384 個哈希槽(hash slot)中的哪個槽,這樣就會對應(yīng)到由哪個主節(jié)點來負責寫數(shù)據(jù)拗军。
這種將哈希槽分布到不同節(jié)點的做法使得用戶可以很容易地向集群中添加或者刪除節(jié)點任洞。 例如:
1蓄喇、如果用戶將新節(jié)點 D 添加到集群中, 那么集群只需要將節(jié)點 A 交掏、B 妆偏、 C 中的某些槽移動到節(jié)點 D 就可以了。
2盅弛、與此類似钱骂, 如果用戶要從集群中移除節(jié)點 A , 那么集群只需要將節(jié)點 A 中的所有哈希槽移動到節(jié)點 B 和節(jié)點 C 挪鹏, 然后再移除空白(不包含任何哈希槽)的節(jié)點 A 就可以了罐柳。
因為將一個哈希槽從一個節(jié)點移動到另一個節(jié)點不會造成節(jié)點阻塞, 所以無論是添加新節(jié)點還是移除已存在節(jié)點狰住, 又或者改變某個節(jié)點包含的哈希槽數(shù)量张吉, 都不會造成集群下線。
為了使得集群在一部分節(jié)點出現(xiàn)故障時催植,集群仍然可以正常運作肮蛹, Redis 集群對節(jié)點使用了主從復(fù)制功能: 集群中的每個節(jié)點都有 1 個至 N 個復(fù)制品(replica), 其中一個復(fù)制品為主節(jié)點(master)创南, 而其余的 N-1 個復(fù)制品為從節(jié)點(slave)伦忠。在之前列舉的節(jié)點 A 、B 稿辙、C 的例子中昆码, 如果節(jié)點 B 下線了, 那么集群將無法正常運行邻储, 因為集群找不到節(jié)點來處理 5501 號至 11000 號的哈希槽赋咽。
這時, 假如在創(chuàng)建集群的時候(或者至少在節(jié)點 B 下線之前)吨娜, 我們?yōu)橹鞴?jié)點 B 添加了從節(jié)點 B1 脓匿, 那么當主節(jié)點 B 下線的時候, 集群就會將 B1 設(shè)置為新的主節(jié)點宦赠, 并讓它代替下線的主節(jié)點 B 陪毡, 繼續(xù)處理 5501 號至 11000 號的哈希槽, 這樣集群就不會因為主節(jié)點 B 的下線而無法正常運作了勾扭。不過如果節(jié)點 B 和 B1 都下線的話毡琉, Redis 集群還是會停止運作。
下面我們用一個具體例子來看下如何對cluster集群環(huán)境進行配置妙色。
(三)配置和創(chuàng)建集群
Redis的cluser集群桅滋,當存活的主節(jié)點數(shù)小于總節(jié)點數(shù)的一半時,整個集群就無法提供服務(wù)了燎斩。這樣的化虱歪,整個最小的cluser集群至少需要3個節(jié)點,即3個主節(jié)點栅表。但是在試用集群功能時笋鄙,強烈建議最少配置6個節(jié)點,即3個主節(jié)點怪瓶,3個從節(jié)點萧落。如果是真實的生產(chǎn)環(huán)境,建議1個主節(jié)點配置3個從節(jié)點洗贰。
下面我們以在一臺機器上搭建6個節(jié)點的cluster集群pe為例來說明找岖,相當于是一個偽分布式的集群環(huán)境。如果是在多臺機器上敛滋,操作類似许布。當然,也可以通過虛擬機或docker來模擬多臺物理機绎晃。
假設(shè)該機器上已經(jīng)有單機的Redis環(huán)境蜜唾,具體可參見《Redis學習筆記1-基礎(chǔ)知識》
文檔。我們在該Redis環(huán)境的根目錄下創(chuàng)建cluster-test目錄庶艾,然后在cluster-test目錄下創(chuàng)建六個以端口號為名字的子目錄(因為是在同一臺機器上測試袁余,所以每個redis實例的端口號不能重復(fù)), 我們會在每個目錄中運行一個 Redis 實例咱揍。命令如下:
mkdir cluster-test
cd cluster-test
mkdir 7000 7001 7002 7003 7004 7005
在文件夾 7000 至 7005 中颖榜, 各創(chuàng)建一個 redis.conf 文件, 文件的內(nèi)容在原始的redis.conf文件基礎(chǔ)上使用下面的示例配置項:
port 7000
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
上面的配置項是集群環(huán)境下需要在默認的配置文件中最小改動的內(nèi)容煤裙,要記得將各個配置文件中的端口號從 7000改為與文件夾名字相同的端口號掩完。cluster-enabled 選項用于開實例的集群模式, 而 cluster-conf-file 選項則設(shè)定了保存節(jié)點配置文件的路徑硼砰, 默認值為 nodes.conf 藤为,節(jié)點配置文件無須人為修改, 它由 Redis 集群在啟動時創(chuàng)建夺刑, 并在有需要時自動進行更新缅疟。
需要說明的是,主從節(jié)點不需要配置遍愿,集群會自動選擇存淫。
下面我們來依次啟動6個redis實例,如啟動第一個實例:
src/redis-server cluster-test/7000/redis.conf
上面的命令一共啟動6次沼填,注意每次需要使用不同的端口號值桅咆。
現(xiàn)在我們已經(jīng)有了6個正在運行中的 Redis 實例, 但這6個實例還沒有組成一個cluster集群環(huán)境坞笙。接下來我們需要將這些實例來創(chuàng)建集群岩饼, 并為每個節(jié)點編寫配置文件(會由下面的操作自動生成荚虚,不需要手工操作)。
通過使用 Redis 提供的集群命令行工具 redis-trib 籍茧, 編寫節(jié)點配置文件的工作可以非常容易地完成版述。 redis-trib 位于 src 文件夾中, 它是一個 Ruby 程序寞冯, 這個程序通過向?qū)嵗l(fā)送特殊命令來完成創(chuàng)建新集群渴析、檢查集群、 或者對集群進行重新分片(reshared)等工作吮龄。
我們需要執(zhí)行以下命令來創(chuàng)建集群:
src/redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001
127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005
命令的意義如下:
1)給定 redis-trib.rb 程序的命令是 create 俭茧, 這表示我們希望創(chuàng)建一個新的集群。
2)選項 --replicas 1 表示我們希望為集群中的每個主節(jié)點創(chuàng)建一個從節(jié)點漓帚。
3)之后跟著的其他參數(shù)則是實例的地址列表母债, 我們希望程序使用這些地址所指示的實例來創(chuàng)建新集群。
簡單來說尝抖, 以上命令的意思就是讓 redis-trib 程序創(chuàng)建一個包含3個主節(jié)點和3個從節(jié)點的集群场斑。
運行上面命令, redis-trib 會在控制臺打印出一份預(yù)想中的配置信息牵署, 并提示如果沒問題就可以輸入 yes 漏隐, redis-trib 就會將這份配置應(yīng)用到集群當中。
輸入 yes 并按下回車確認之后奴迅, 集群就會將配置應(yīng)用到各個節(jié)點青责, 并連接起(join)各個節(jié)點 —— 也即是, 讓各個節(jié)點開始互相通訊取具。如果一切正常的話脖隶, redis-trib 將輸出以下信息:
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
這表示集群中的 16384 個槽都有至少一個主節(jié)點在處理, 集群運作正常暇检。
(四)測試集群
我們可以使用redis的命令行程序來測試集群产阱,如下面示例:
$src/redis-cli -c -p 7000
redis 127.0.0.1:7000> set foo bar
-> Redirected to slot [12182] located at 127.0.0.1:7002
OK
redis 127.0.0.1:7002> set hello world
-> Redirected to slot [866] located at 127.0.0.1:7000
OK
redis 127.0.0.1:7000> get foo
-> Redirected to slot [12182] located at 127.0.0.1:7002
"bar"
redis 127.0.0.1:7000> get hello
-> Redirected to slot [866] located at 127.0.0.1:7000
"world"
可以看出,redis cluster集群的特點块仆,它是去中心化的构蹬,每個節(jié)點都是對等的,連接哪個節(jié)點都可以獲取和設(shè)置數(shù)據(jù)悔据。redis-cli 對集群的支持是非匙玻基本的, 它總是依靠 Redis 集群來將它轉(zhuǎn)向(redirect)至正確的節(jié)點科汗。一個真正的集群客戶端應(yīng)該做得比這更好: 它應(yīng)該用緩存記錄起哈希槽與節(jié)點地址之間的映射(map)藻烤, 從而直接將命令發(fā)送到正確的節(jié)點上面。
我們也可以故意讓某個redis主實例停止,來測試集群是否會自動完成替換操作怖亭,這個具體就不再演示涎显。
五、小結(jié)
本文介紹了Redis的集群模式兴猩,Redis有三種集群模式期吓,主從模式是個基礎(chǔ),但不能滿足生產(chǎn)環(huán)境的要求峭跳;sentinel模式可以滿足一般的生產(chǎn)環(huán)境膘婶,但在大數(shù)據(jù)場景下就有問題缺前;cluster模式是一個真正的分布式集群系統(tǒng)蛀醉,可以滿足大數(shù)據(jù)場景下的應(yīng)用。