redis cluster(1)- 集羣安裝配置詳解

 

總結:

1、簡介


Redis Cluster是一個高性能高可用的分佈式系統。由多個Redis實例組成的整體,數據按照Slot存儲分佈在多個Redis實例上,通過Gossip協議來進行節點之間通信。

1.1Redis集羣核心的目標:

官方文檔Cluster Spec中,作者詳細介紹了Redis集羣爲什麼要設計成現在的樣子。最核心的目標有三個:

1、性能:這是Redis賴以生存的看家本領,增加集羣功能後當然不能對性能產生太大影響,所以Redis採取了P2P而非Proxy方式、Master與slave之間使用異步複製(異步replication)、客戶端重定向等設計,而犧牲了部分的一致性、使用性。

2、水平擴展:集羣的最重要能力當然是擴展,文檔中稱可以線性擴展到1000結點。

3、可用性:在Cluster推出之前,可用性要靠Sentinel保證。有了集羣之後也自動具有了Sentinel的監控和自動Failover能力。只要集羣中大多數master可達、且失效的master至少有一個slave可達時,集羣都可以繼續提供服務;同時“replicas migration”可以將那些擁有多個slaves的master的某個slave,遷移到沒有slave的master下,即將slaves的分佈在整個集羣相對平衡,盡力確保每個master都有一定數量的slave備份。

4、數據一致性:客戶端容忍一定程度的數據丟失,集羣儘可能保存Client write操作的數據,保證數據一致性。集羣將會儘可能(best-effort)保存客戶端write操作的數據;通常在failover期間,會有短暫時間內的數據丟失(因爲異步replication引起);當客戶端與少數派的節點處於網絡分區時(network partition),丟失數據的可能性會更高。(因爲節點有效性檢測、failover需要更長的時間)

Redis Cluster功能特點如下:

1)節點自動發現:所有的節點相互連接

2)集羣消息通信通過集羣總線通信,,集羣總線端口大小爲客戶端服務端口+10000,這個10000是固定值

3)節點與節點之間通過二進制協議進行通信

4)客戶端和集羣節點之間通信和通常一樣,通過文本協議進行

5)集羣節點不會代理查詢

6)數據按照Slot存儲分佈在多個Redis實例上

7)集羣節點掛掉會自動故障轉移

8)可以相對平滑擴/縮容節點

 

1.2 架構變化與CAP理論:

Redis Cluster集羣功能推出已經有一段時間了。在單機版的Redis中,每個Master之間是沒有任何通信的,所以我們一般在Jedis客戶端或者Codis這樣的代理中做Pre-sharding。按照CAP理論來說,單機版的Redis屬於保證CP(Consistency & Partition-Tolerancy)而犧牲A(Availability),也就說Redis能夠保證所有用戶看到相同的數據(一致性,因爲Redis不自動冗餘數據)和網絡通信出問題時,暫時隔離開的子系統能繼續運行(分區容忍性,因爲Master之間沒有直接關係,不需要通信),但是不保證某些結點故障時,所有請求都能被響應(可用性,某個Master結點掛了的話,那麼它上面分片的數據就無法訪問了)。

有了Cluster功能後,Redis從一個單純的NoSQL內存數據庫變成了分佈式NoSQL數據庫,CAP模型也從CP變成了AP。也就是說,通過自動分片和冗餘數據,Redis具有了真正的分佈式能力,某個結點掛了的話,因爲數據在其他結點上有備份,所以其他結點頂上來就可以繼續提供服務,保證了Availability。然而,也正因爲這一點,Redis無法保證曾經的強一致性了。這也是CAP理論要求的,三者只能取其二。

1.3 和單點操作變化

Cluster不能進行跨Nodes操作,也沒有nodes提供merge層代理。

Cluster中實現了一個稱爲“hash tags”的概念,每個key都可以包含一個自定義的“tags”,那麼在存儲時將根據tags計算此key應該分佈在哪個nodes上(而不是使用key計算,但是存儲層面仍然是key);此特性,可以強制某些keys被保存在同一個節點上,以便於進行“multikey”操作,比如“foo”和“{foo}.student”將會被保存在同一個node上。不過在人工對slots進行resharding期間,multikey操作可能不可用。

在Cluster環境下,將不支持SELECT命令,所有的key都將保存在默認的database中。

1.4 客戶端與Server角色

集羣中nodes負責存儲數據,保持集羣的狀態,包括keys與nodes的對應關係(內部其實爲slots與nodes對應關係)。nodes也能夠自動發現其他的nodes,檢測失效的節點,當某個master失效時還應該能將合適的slave提升爲master。

爲了達成這些行爲,集羣中的每個節點都通過TCP與其他所有nodes建立連接Nodes之間使用gossip協議(參見下文備註)向其他nodes傳播集羣信息,以達到自動發現的特性,通過發送ping來確認其他nodes工作正常,也會在合適的時機發送集羣的信息。當然在Failover時(包括人爲failover)也會使用Bus來傳播消息。

Nodes之間使用gossip協議(參見下文備註)向其他nodes傳播集羣信息,以達到自動發現的特性,通過發送ping來確認其他nodes工作正常,也會在合適的時機發送集羣的信息。當然在Failover時(包括人爲failover)也會使用Bus來傳播消息。

理論上,Client可以將請求發送給任意一個nodes,然後根據在根據錯誤信息轉發給合適的node,客戶端可以不用保存集羣的狀態信息,當然這種情況下性能比較低效,因爲Client可能需要2次TCP調用才能獲取key的結果,通常客戶端會緩存集羣中nodes與slots的映射關係,並在遇到“Redirected”錯誤反饋時,纔會更新本地的緩存。上,Client可以將請求發送給任意一個nodes,然後根據在根據錯誤信息轉發給合適的node,客戶端可以不用保存集羣的狀態信息,當然這種情況下性能比較低效,因爲Client可能需要2次TCP調用才能獲取key的結果,通常客戶端會緩存集羣中nodes與slots的映射關係,並在遇到“Redirected”錯誤反饋時,纔會更新本地的緩存。

 

2、集羣配置安裝


2.1 Redis Cluster 3.2.3安裝:

Redis的安裝很簡單:

mkdir /mnt/src && cd /mnt/src ;
wget http://download.redis.io/releases/redis-3.2.3.tar.gz
tar xzf redis-3.2.3.tar.gz 
cd redis-3.2.3
make && make install

2.2 單機啓動:

#啓動redis 
redis-server /mnt/redis-7001/redis.conf

#連接redis 
redis-cli -a passwd -p 7001 

#查看版本
redis-cli -a passwd -p 7001 info|grep 'redis_version'

#測試是否成功
登錄後執行:ping
收到:pong

 

2.3 redis集羣配置

要想開啓Redis Cluster模式,有幾項配置是必須的。此外爲了方便使用和後續的測試,我還額外做了一些配置:

  • 綁定地址:bind 192.168.XXX.XXX。不能綁定到127.0.0.1或localhost,否則指導客戶端重定向時會報”Connection refused”的錯誤。
  • 開啓Cluster:cluster-enabled yes :如果想在特定的Redis實例中啓用Redis羣集支持就設置爲yes。 否則,實例通常作爲獨立實例啓動。
  • 集羣配置文件:cluster-config-file nodes-7000.conf。這個配置文件不是要我們去配的,而是Redis運行時保存配置的文件,所以我們也不可以修改這個文件。Redis羣集節點每次發生更改時自動保留羣集配置(基本上爲狀態)的文件,以便能夠 在啓動時重新讀取它。 該文件列出了羣集中其他節點,它們的狀態,持久變量等等。 由於某些消息的接收,通常會將此文件重寫並刷新到磁盤上。
  • 集羣超時時間:cluster-node-timeout 15000。結點超時多久則認爲它宕機了。如果主節點超過指定的時間不可達,它將由其從屬設備進行故障切換。 此參數控制Redis羣集中的其他重要事項。 值得注意的是,每個無法在指定時間內到達大多數主節點的節點將停止接受查詢。
  • 槽是否全覆蓋:cluster-require-full-coverage no。默認是yes,只要有結點宕機導致16384個槽沒全被覆蓋,整個集羣就全部停止服務,所以一定要改爲no。 如果將其設置爲yes,則默認情況下,如果key的空間的某個百分比未被任何節點覆蓋,則集羣停止接受寫入。 如果該選項設置爲no,則即使只處理關於keys子集的請求,羣集仍將提供查詢。
  • 後臺運行:daemonize yes
  • 輸出日誌:logfile “./redis.log”
  • 監聽端口:port 7000
  • cluster-slave-validity-factor <factor>:如果設置爲0,無論主設備和從設備之間的鏈路保持斷開連接的時間長短,從設備都將嘗試故障切換主設備。 如果該值爲正值,則計算最大斷開時間作爲節點超時值乘以此選項提供的係數,如果該節點是從節點,則在主鏈路斷開連接的時間超過指定的超時值時,它不會嘗試啓動故障切換。 例如,如果節點超時設置爲5秒,並且有效因子設置爲10,則與主設備斷開連接超過50秒的從設備將不會嘗試對其主設備進行故障切換。 請注意,如果沒有從服務器節點能夠對其進行故障轉移,則任何非零值都可能導致Redis羣集在主服務器出現故障後不可用。 在這種情況下,只有原始主節點重新加入集羣時,集羣纔會返回可用。
  • cluster-migration-barrier <count>:主設備將保持連接的最小從設備數量,以便另一個從設備遷移到不受任何從設備覆蓋的主設備。有關更多信息,請參閱本教程中有關副本遷移的相應部分。
     

配置好後,根據我們的集羣規模,拷貝出來幾份同樣的配置文件,唯一不同的就是監聽端口,可以依次改爲7001、7002… 因爲Redis Cluster如果數據冗餘是1的話,至少要3個Master和3個Slave,所以我們拷貝出6個實例的配置文件。爲了避免相互影響,爲6個實例的配置文件建立獨立的文件夾。

2.4 redis-trib管理器

Redis作者應該是個Ruby愛好者,Ruby客戶端就是他開發的。這次集羣的管理功能沒有嵌入到Redis代碼中,於是作者又順手寫了個叫做redis-trib的管理腳本。redis-trib依賴Ruby和RubyGems,以及redis擴展。可以先用which命令查看是否已安裝ruby和rubygems,用gem list –local查看本地是否已安裝redis擴展。

最簡便的方法就是用apt或yum包管理器安裝RubyGems後執行gem install redis。如果網絡或環境受限的話,可以手動安裝RubyGems和redis擴展

#安裝rub管理工具rvm
gpg2 --keyserver hkp://keys.gnupg.net --recv-keys D39DC0E3
curl -L get.rvm.io | bash -s stable
find / -name rvm -print
#加載rvm
source /usr/local/rvm/scripts/rvm
#查看ruby版本
 rvm list known
#安裝ruby,這裏我們選擇安裝2.5.1
rvm install 2.5.1
rvm use 2.5.1 --default
#安裝redis-trib.rb即redis集羣工具
gem install redis -v 3.3.5

#安裝完成後的目錄爲:
/mnt/src/redis-4.0.9/src/redis-trib.rb

        

2.5 啓動集羣服務

首先,啓動我們配置好的6個Redis實例。我們創建相關目錄,主文件夾是redis-cluster,在此文件夾下建立6個子文件夾,名稱分別是:7001,7002,7003,7004,7005,7006 該目錄以我們將在任何給定目錄內運行的實例的端口號命名。

mkdir -p /data/redis-cluster-{7001..7006} && 
touch /data/redis-cluster-{7001..7006}/redis.log
#啓動redis 
redis-server /data/redis-7001/redis.conf

此時6個實例還沒有形成集羣,現在用redis-trb.rb管理腳本建立起集羣。可以看到,redis-trib默認用前3個實例作爲Master,後3個作爲Slave。因爲Redis基於Master-Slave做數據備份,而非像Cassandra或Hazelcast一樣不區分結點角色,自動複製並分配Slot的位置到各個結點。 

#啓動集羣
/mnt/src/redis-4.0.9/src/redis-trib.rb  create  --replicas  1 10.26.25.115:7001 10.26.25.115:7002 10.26.25.115:7003 10.26.25.115:7004 10.26.25.115:7005 10.26.25.115:7006 
至此,集羣就已經建立成功了!“貼心”的Redis還在utils/create-cluster下提供了一個create-cluster腳本,能夠創建出一個集羣,類似我們上面建立起的3主3從的集羣。

 

2.6 簡單測試

我們連接到集羣中的任意一個結點,啓動redis-cli時要加-c選項,存取兩個Key-Value感受一下Redis久違的集羣功能。

仔細觀察能夠注意到,redis-cli根據指示,不斷在7000和7002結點之前重定向跳轉。如果啓動時不加-c選項的話,就能看到以錯誤形式顯示出的MOVED重定向消息。

 

2.7 集羣重啓

目前redis-trib的功能還比較弱,需要重啓集羣的話先手動kill掉各個進程,然後重新啓動就可以了。這也有點太… 網上有人重啓後會碰到問題,我還比較幸運,這種“土鱉”的方式重啓試了兩次還沒發現問題。

[root@8gVm redis-3.0.4]# ps -ef | grep redis | awk '{print $2}' | xargs kill

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章