前提:先安裝好Redis,參考:http://www.cnblogs.com/EasonJim/p/7599941.htmlhtml
說明:Redis Cluster集羣模式能夠作到動態增長節點和下線節點,使用起來很是的方便。node
下面教程主要是經過官方提供的文檔進行搭建測試:mysql
https://redis.io/topics/cluster-tutorialredis
http://www.redis.cn/topics/cluster-tutorial.html算法
http://ifeve.com/redis-cluster-tutorial/sql
http://ifeve.com/redis-cluster-spec/(翻譯自官方高級使用教程)數據庫
上面中文教程均可以在官方提供的文檔中找到。vim
原理應該以下圖所示:ruby
注意:如下的搭建教程比較簡單,基於僞集羣的模式,若是是生產環境能夠每臺機部署一個實例。操做基本一致。bash
這篇教程是Redis集羣的簡要介紹,而非講解分佈式系統的複雜概念。它主要從一個使用者的角度介紹如何搭建、測試和使用Redis集羣,至於Redis集羣的詳細設計將在「Redis集羣規範」中進行描述。
本教程以redis使用者的角度,用簡單易懂的方式介紹Redis集羣的可用性和一致性。
注意: 本教程要求Redis3.0或以上的版本。
若是你打算部署Redis集羣,你能夠讀一些關於集羣的詳細設計,固然,這不是必須的。由這篇教程入門,先大概使用一下Redis的集羣,而後再讀Redis集羣的詳細設計,也是不錯的選擇。
Redis集羣 101
Redis集羣在啓動的時候就自動在多個節點間分好片。同時提供了分片之間的可用性:當一部分redis節點故障或網絡中斷,集羣也能繼續工做。可是,當大面積的節點故障或網絡中斷(好比大部分的主節點都不可用了),集羣就不能使用。
因此,從實用性的角度,Redis集羣提供如下功能:
- 自動把數據切分到多個Redis節點中
- 當一部分節點掛了或不可達,集羣依然能繼續工做
Redis集羣的TCP端口
Redis集羣中的每一個節點都須要創建2個TCP鏈接,監聽這2個端口:一個端口稱之爲「客戶端端口」,用於接受客戶端指令,與客戶端交互,好比6379;另外一個端口稱之爲「集羣總線端口」,是在客戶端端口號上加10000,好比16379,用於節點之間經過二進制協議通信。各節點經過集羣總線檢測宕機節點、更新配置、故障轉移驗證等。客戶端只能使用客戶端端口,不能使用集羣總線端口。請確保你的防火牆容許打開這兩個端口,不然Redis集羣無法工做。客戶端端口和集羣總線端口之間的差值是固定的,集羣總線端口比客戶端端口高10000。
注意,關於集羣的2個端口:
- 客戶端端口(通常是6379)須要對全部客戶端和集羣節點開放,由於集羣節點須要經過該端口轉移數據。
- 集羣總線端口(通常是16379)只需對集羣中的全部節點開放
這2個端口必須打開,不然集羣無法正常工做。
集羣節點之間經過集羣總線端口交互數據,使用的協議不一樣於客戶端的協議,是二進制協議,這能夠減小帶寬和處理時間。
Redis集羣數據的分片
Redis集羣不是使用一致性哈希,而是使用哈希槽。整個Redis集羣有16384個哈希槽,決定一個key應該分配到那個槽的算法是:計算該key的CRC16結果再模16834。
集羣中的每一個節點負責一部分哈希槽,好比集羣中有3個節點,則:
- 節點A存儲的哈希槽範圍是:0 – 5500
- 節點B存儲的哈希槽範圍是:5501 – 11000
- 節點C存儲的哈希槽範圍是:11001 – 16384
這樣的分佈方式方便節點的添加和刪除。好比,須要新增一個節點D,只須要把A、B、C中的部分哈希槽數據移到D節點。一樣,若是但願在集羣中刪除A節點,只須要把A節點的哈希槽的數據移到B和C節點,當A節點的數據所有被移走後,A節點就能夠徹底從集羣中刪除。
由於把哈希槽從一個節點移到另外一個節點是不須要停機的,因此,增長或刪除節點,或更改節點上的哈希槽,也是不須要停機的。
若是多個key都屬於一個哈希槽,集羣支持經過一個命令(或事務, 或lua腳本)同時操做這些key。經過「哈希標籤」的概念,用戶可讓多個key分配到同一個哈希槽。哈希標籤在集羣詳細文檔中有描述,這裏作個簡單介紹:若是key含有大括號」{}」,則只有大括號中的字符串會參與哈希,好比」this{foo}」和」another{foo}」這2個key會分配到同一個哈希槽,因此能夠在一個命令中同時操做他們。
Redis集羣的主從模式
爲了保證在部分節點故障或網絡不通時集羣依然能正常工做,集羣使用了主從模型,每一個哈希槽有一(主節點)到N個副本(N-1個從節點)。在咱們剛纔的集羣例子中,有A,B,C三個節點,若是B節點故障集羣就不能正常工做了,由於B節點中的哈希槽數據無法操做。可是,若是咱們給每個節點都增長一個從節點,就變成了:A,B,C三個節點是主節點,A1, B1, C1 分別是他們的從節點,當B節點宕機時,咱們的集羣也能正常運做。B1節點是B節點的副本,若是B節點故障,集羣會提高B1爲主節點,從而讓集羣繼續正常工做。可是,若是B和B1同時故障,集羣就不能繼續工做了。
Redis集羣的一致性保證
Redis集羣不能保證強一致性。一些已經向客戶端確認寫成功的操做,會在某些不肯定的狀況下丟失。
產生寫操做丟失的第一個緣由,是由於主從節點之間使用了異步的方式來同步數據。
一個寫操做是這樣一個流程:
1)客戶端向主節點B發起寫的操做
2)主節點B迴應客戶端寫操做成功
3)主節點B向它的從節點B1,B2,B3同步該寫操做
從上面的流程能夠看出來,主節點B並無等從節點B1,B2,B3寫完以後再回復客戶端此次操做的結果。因此,若是主節點B在通知客戶端寫操做成功以後,但同步給從節點以前,主節點B故障了,其中一個沒有收到該寫操做的從節點會晉升成主節點,該寫操做就這樣永遠丟失了。
就像傳統的數據庫,在不涉及到分佈式的狀況下,它每秒寫回磁盤。爲了提升一致性,能夠在寫盤完成以後再回復客戶端,但這樣就要損失性能。這種方式就等於Redis集羣使用同步複製的方式。
基本上,在性能和一致性之間,須要一個權衡。
若是真的須要,Redis集羣支持同步複製的方式,經過WAIT指令來實現,這可讓丟失寫操做的可能性降到很低。但就算使用了同步複製的方式,Redis集羣依然不是強一致性的,在某些複雜的狀況下,好比從節點在與主節點失去鏈接以後被選爲主節點,不一致性仍是會發生。
這種不一致性發生的狀況是這樣的,當客戶端與少數的節點(至少含有一個主節點)網絡聯通,但他們與其餘大多數節點網絡不通。好比6個節點,A,B,C是主節點,A1,B1,C1分別是他們的從節點,一個客戶端稱之爲Z1。
當網絡出問題時,他們被分紅2組網絡,組內網絡聯通,但2組之間的網絡不通,假設A,C,A1,B1,C1彼此之間是聯通的,另外一邊,B和Z1的網絡是聯通的。Z1能夠繼續往B發起寫操做,B也接受Z1的寫操做。當網絡恢復時,若是這個時間間隔足夠短,集羣仍然能繼續正常工做。若是時間比較長,以至B1在大多數的這邊被選爲主節點,那剛纔Z1發給B的寫操做都將丟失。
注意,Z1給B發送寫操做是有一個限制的,若是時間長度達到了大多數節點那邊能夠選出一個新的主節點時,少數這邊的全部主節點都不接受寫操做。
這個時間的配置,稱之爲節點超時(node timeout),對集羣來講很是重要,當達到了這個節點超時的時間以後,主節點被認爲已經宕機,能夠用它的一個從節點來代替。一樣,在節點超時時,若是主節點依然不能聯繫到其餘主節點,它將進入錯誤狀態,再也不接受寫操做。
Redis集羣參數配置
咱們後面會部署一個Redis集羣做爲例子,在那以前,先介紹一下集羣在redis.conf中的參數。
- cluster-enabled
<yes/no>
: 若是配置」yes」則開啓集羣功能,此redis實例做爲集羣的一個節點,不然,它是一個普通的單一的redis實例。- cluster-config-file
<filename>
: 注意:雖然此配置的名字叫「集羣配置文件」,可是此配置文件不能人工編輯,它是集羣節點自動維護的文件,主要用於記錄集羣中有哪些節點、他們的狀態以及一些持久化參數等,方便在重啓時恢復這些狀態。一般是在收到請求以後這個文件就會被更新。- cluster-node-timeout
<milliseconds>
: 這是集羣中的節點可以失聯的最大時間,超過這個時間,該節點就會被認爲故障。若是主節點超過這個時間仍是不可達,則用它的從節點將啓動故障遷移,升級成主節點。注意,任何一個節點在這個時間以內若是仍是沒有連上大部分的主節點,則此節點將中止接收任何請求。- cluster-slave-validity-factor
<factor>
: 若是設置成0,則不管從節點與主節點失聯多久,從節點都會嘗試升級成主節點。若是設置成正數,則cluster-node-timeout乘以cluster-slave-validity-factor獲得的時間,是從節點與主節點失聯後,此從節點數據有效的最長時間,超過這個時間,從節點不會啓動故障遷移。假設cluster-node-timeout=5,cluster-slave-validity-factor=10,則若是從節點跟主節點失聯超過50秒,此從節點不能成爲主節點。注意,若是此參數配置爲非0,將可能出現因爲某主節點失聯卻沒有從節點能頂上的狀況,從而致使集羣不能正常工做,在這種狀況下,只有等到原來的主節點從新迴歸到集羣,集羣才恢復運做。- cluster-migration-barrier
<count>
:主節點須要的最小從節點數,只有達到這個數,主節點失敗時,它從節點纔會進行遷移。更詳細介紹能夠看本教程後面關於副本遷移到部分。- cluster-require-full-coverage <yes/no>:在部分key所在的節點不可用時,若是此參數設置爲」yes」(默認值), 則整個集羣中止接受操做;若是此參數設置爲」no」,則集羣依然爲可達節點上的key提供讀操做。
建立和使用Redis集羣
注意:手動部署Redis集羣可以很好的瞭解它是如何運做的,但若是你但願儘快的讓集羣運行起來,能夠跳過本節和下一節,直接到」使用create-cluster腳本建立Redis集羣」章節。
要建立集羣,首先須要以集羣模式運行的空redis實例。也就說,以普通模式啓動的redis是不能做爲集羣的節點的,須要以集羣模式啓動的redis實例纔能有集羣節點的特性、支持集羣的指令,成爲集羣的節點。
下面是最小的redis集羣的配置文件(redis.conf):
port 7000 cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes開啓集羣模式只需打開cluster-enabled配置項便可。每個redis實例都包含一個配置文件,默認是nodes.conf(啓動時會自動生成),用於存儲此節點的一些配置信息。這個配置文件由redis集羣的節點自行建立和更新,不能由人手動地去修改。
一個最小的集羣須要最少3個主節點。第一次測試,強烈建議你配置6個節點:3個主節點和3個從節點。
開始測試,步驟以下:先進入新的目錄,以redis實例的端口爲目錄名,建立目錄,咱們將在這些目錄裏運行咱們的實例。
相似這樣:
mkdir cluster-test cd cluster-test mkdir 7000 7001 7002 7003 7004 7005在7000-7005的每一個目錄中建立配置文件redis.conf,內容就用上面的最簡配置作模板,注意修改端口號,改成跟目錄一致的端口。
把你的Redis服務器(用GitHub中的不穩定分支的最新的代碼編譯來/或者穩定代碼)拷貝到cluster-test目錄,而後打開6個終端頁準備測試。
第一臺:
在每一個終端啓動一個redis實例,指令相似這樣:
cd 7000 ../redis-server ./redis.conf
在日誌中咱們能夠看到,因爲沒有nodes.conf文件不存在,每一個節點都給本身一個新的ID。
[82462] 26 Nov 11:56:55.329 * No cluster configuration found, I'm 97a3a64667477371c4479320d683e4c8db5858b1這個ID將一直被此節點使用,做爲此節點在整個集羣中的惟一標識。節點區分其餘節點也是經過此ID來標識,而非IP或端口。IP能夠改,端口能夠改,但此ID不能改,直到這個節點離開集羣。這個ID稱之爲節點ID(Node ID)。
第二臺:
第三臺:
第四臺:
第五臺:
第六臺:
重複第一臺的操做。
建立集羣
如今6個實例已經運行起來了,咱們須要給節點寫一些有意義的配置來建立集羣。redis集羣的命令工具redis-trib可讓咱們建立集羣變得很是簡單。redis-trib是一個用ruby寫的腳本,用於給各節點發指令建立集羣、檢查集羣狀態或給集羣從新分片等。redis-trib在Redis源碼的src目錄下,須要gem redis來運行redis-trib。
gem install redis建立集羣只需輸入指令:
./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這裏用的命令是create,由於咱們須要建立一個新的集羣。選項」–replicas 1」表示每一個主節點須要一個從節點。其餘參數就是須要加入這個集羣的Redis實例的地址。
咱們建立的集羣有3個主節點和3個從節點。
redis-trib會給你一些配置建議,輸入yes表示接受。集羣會被配置並彼此鏈接好,意思是各節點實例被引導彼此通話並最終造成集羣。最後,若是一切順利,會看到相似下面的信息:
[OK] All 16384 slots covered這表示,16384個哈希槽都被主節點正常服務着。
使用create-cluster腳本建立redis集羣
若是你不想像上面那樣,單獨的手工配置各節點的方式來建立集羣,還有一個更簡單的系統(固然也無法瞭解到集羣運做的一些細節)。
在utils/create-cluster目錄下,有一個名爲create-cluster的bash腳本。若是須要啓動一個有3個主節點和3個從節點的集羣,只須要輸入如下指令
#1
create-cluster start #2
create-cluster create在步驟2,當redis-trib要你接受集羣的佈局時,輸入」yes」。
如今你能夠跟集羣交互,第一個節點的起始端口默認是30001。當你完成後,中止集羣用以下指令:
create-cluster stop請查看目錄下的README,它有詳細的介紹如何使用此腳本。
實際操做以下:
版本:4.0.2
下載地址:https://redis.io/download
離線版本:(連接: https://pan.baidu.com/s/1bpwDtOr 密碼: 4cxk)
源碼編譯:
wget http://download.redis.io/releases/redis-4.0.2.tar.gz tar xzf redis-4.0.2.tar.gz cd redis-4.0.2 make
若是不安裝到指定位置,那麼程序默認放在src文件夾下,
建立集羣文件及文件夾:
mkdir cluster-test cd cluster-test mkdir 7000 7001 7002 7003 7004 7005
進入7000建立redis.conf,內容以下:
cd 7000 sudo vim redis.conf #內容 port 7000 cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes
進入7001建立redis.conf,內容以下:
cd 7001
sudo vim redis.conf #內容 port 7001 cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes
進入7002建立redis.conf,內容以下:
cd 7002
sudo vim redis.conf #內容 port 7002 cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes
進入7003建立redis.conf,內容以下:
cd 7003
sudo vim redis.conf #內容 port 7003 cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes
進入7004建立redis.conf,內容以下:
cd 7004
sudo vim redis.conf #內容 port 7004 cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes
進入7005建立redis.conf,內容以下:
cd 7005
sudo vim redis.conf #內容 port 7005 cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes
分別啓動6臺集羣:
cd 7000
../redis-server ./redis.conf
cd 7001 ../redis-server ./redis.conf
cd 7002 ../redis-server ./redis.conf
cd 7003 ../redis-server ./redis.conf
cd 7004 ../redis-server ./redis.conf
cd 7005 ../redis-server ./redis.conf
建立集羣:
先安裝ruby
sudo apt-get ruby
進入src文件夾
再經過gem安裝redis
cd src gem install redis
若是出現錯誤,參考:http://www.cnblogs.com/EasonJim/p/7629314.html
啓動
./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
期間會提示輸入yes,而後基本完成。輸出的信息上有提示哪些是主節點和從節點。
參考:
http://ifeve.com/redis-cluster-tutorial/(以上內容部分轉自此篇文章)
http://blog.csdn.net/fengshizty/article/details/51368004 (節點操做的測試)
http://www.redis.cn/topics/cluster-tutorial.html
http://ifeve.com/redis-cluster-spec/
http://os.51cto.com/art/201512/499551.htm
http://blog.csdn.net/robertohuang/article/details/70766809
http://blog.csdn.net/robertohuang/article/details/70768922
http://blog.csdn.net/robertohuang/article/details/70833231
http://blog.chinaunix.net/uid-28396214-id-4981572.html
http://blog.51yip.com/nosql/1725.html
http://www.cnblogs.com/wuxl360/p/5920330.html
http://blog.csdn.net/men_wen/article/details/72853078