1. 程式人生 > >淘淘商城系列——Redis叢集的搭建

淘淘商城系列——Redis叢集的搭建

本文我將帶領大家如何搭建Redis叢集。首先說一下,為何要搭建Redis叢集。Redis是在記憶體中儲存資料的,而我們的電腦一般記憶體都不大,這也就意味著Redis不適合儲存大資料,適合儲存大資料的是Hadoop生態系統的Hbase或者是MogoDB。Redis更適合處理高併發,一臺裝置的儲存能力是很有限的,但是多臺裝置協同合作,就可以讓記憶體增大很多倍,這就需要用到叢集。

redis-cluster架構圖

我們來看一下redis-cluster架構圖,如下圖所示。可以看到Redis叢集是沒有統一入口的,客戶端連叢集中的哪臺裝置都行,叢集中各個裝置之間都定時進行互動,以便知道節點是否還正常工作。
這裡寫圖片描述


我按照我個人的理解說一下叢集架構中的一些細節:

  1. 上圖中的藍圈表示的都是節點,每個節點和節點之間使用PING-PONG機制來相互通訊,內部使用二進位制協議優化傳輸速度和頻寬。
  2. 在整個叢集內部,沒有一個代理層,也就是說叢集中沒有哪個節點是入口。也即客戶端要連叢集的話,連叢集中的哪個節點都行,只要連上其中一個,那麼這時你就可以通過這個節點訪問叢集中任意一個節點了。
  3. 我們現在叢集中有這麼多節點,節點上面儲存的資料都是一樣的嗎?如果儲存的資料要是一樣的話,那這個叢集其實意義並不太大,頂多也算是一個儲備。Redis的所有資料都是儲存到記憶體中的,記憶體能放的東西其實並不太多,如果資料量很大的話,那麼這時候一臺伺服器就會存不下,你就算加多少個備份機也不能解決該問題。而你要想解決這個儲存容量的問題,那麼需要保證每個節點上面存放的資料不一樣。如果其中一個節點掛了呢?整個叢集中的這些節點資料就不完整了,如果有其中任意一個節點掛了,那麼叢集就掛了,你要想讓它不掛,每一個節點就應有一個備份機,如果主節點掛了,那麼備份機就頂上來。那麼如何判斷一個節點掛了呢?——節點掛了是通過叢集中超過半數的節點投票(投票機制)決定的,如果超過半數的節點認為這個節點它掛了,那麼它就掛了,沒掛也掛。
    說得更細緻一點,Redis叢集是有容錯投票機制的,如下圖所示。淺黃色的那個節點向紅色的那個節點發出ping命令,紅色節點沒有迴應,這時淺黃色節點便認為這個節點可能掛掉了,它會投上一票,不過這時只是疑問,所以淺黃色節點畫了一個”?”,然後淺黃色節點告訴別的節點說這個紅色的節點可能掛掉了,第二個節點去嘗試和這個紅色節點聯絡,發現也ping不同,於是第二個節點也認為這個紅色節點掛掉了,第二個節點也投上一票,接著第三個節點去和紅色節點聯絡,也聯絡不上,於是也投上一票,這樣便三票了。Redis的容錯投票機制是叢集中過半數的節點認為某個節點掛了,那麼就認定這個節點掛了。這時要看這個紅色節點還有沒有備用節點,如果沒有備用節點了,那麼整個叢集將停止對外提供服務,如果有備份節點,那麼會將備份節點扶正,繼續對外提供服務。
    這裡寫圖片描述
  4. 我們要把資料分散儲存到不同的節點,這時我們如何確定我的這個資料儲存到哪個節點上呢?這個時候Redis叢集引入另外一個概念,就是這個概念,槽的數量是固定的,一共16384個槽。我們先把這個槽分配到不同節點上,每個節點分配一定數量的槽,反正加起來一共16384個槽。當我們要往裡面儲存某個key的時候,先計算一下這個key它應該在哪個槽上,計算完了之後,這個槽分配到哪個伺服器上,我們是知道的。所以,我們就找到對應的伺服器,然後把key存到該伺服器上就可以了。
    Redis叢集內建了16384個雜湊槽,當需要在Redis叢集中放置一個key-value時,Redis先對key使用crc16演算法算出一個結果,然後把結果對16384求餘數,這樣每個key都會對應一個編號在0-16383之間的雜湊槽,redis會根據節點數量大致均等的將雜湊對映到不同的節點。我們以下圖為例,我們把這16384個雜湊槽分配到三個Server上,假如Server1上卡槽是0-5000,Server2上卡槽是5001-10000,Server3上卡槽是10001-16383。假如我們要儲存字串”Hello”,而”Hello”經過crc16演算法再對16384求餘後是500,很顯然應該存到Server1上,假如要儲存的字串”Hello2”經過crc16演算法再對16384求餘後是11500,那麼很顯然應該存到Server3上,同理,”Hello3”、”Hello1”被分別存到Server2和Server1上了。也就是說每個Server其實儲存的內容是不一樣的,這也就是為何某個節點掛掉後如果沒有備用節點的話,整個叢集都會掛掉,因為資料不全了啊。另外,關於每個伺服器上卡槽的分佈數量可以根據伺服器的效能來定,效能好的可以多分配些卡槽,這樣在它上面儲存的內容也就多了。
    這裡寫圖片描述

Redis叢集的搭建

下面我們來搭建Redis叢集,由於叢集的容錯機制是超過半數的節點認為某節點掛掉就確認掛掉,因此我們搭建的叢集最好是奇數臺(>=3)。又由於為了高可用性,每個節點需要有備份節點,因此我們搭建一個Redis叢集至少要有6臺虛擬機器。這樣的話,我們需要6臺虛擬機器,我們的本機又確實跑不了6臺虛擬機器,但我們還想搭建Redis叢集,那怎麼辦呢?其實很簡單,只能搭建偽分散式叢集了,可想而知並不是真正的叢集。具體做法是可以使用一臺虛擬機器執行6個Redis例項,每個Redis例項需要執行在不同的埠,這裡我假設為7001-7006這6個埠。

在一臺虛擬機器上建立6個Redis例項

我相信大家都知道了如何在一臺虛擬機器上建立一個Redis例項,如果讀者還不會,可以通過我的這篇文章進行學習。
首先我們在/usr/local目錄下建立一個redis-cluster目錄,如下圖所示。
這裡寫圖片描述
接著我們將redis/bin目錄複製到redis-cluster/redis01目錄下,如果redis-cluster目錄下沒有redis01這個目錄的,則建立該目錄,如下圖所示。
這裡寫圖片描述
緊接著我們進入redis-cluster/redis01目錄中,並使用ll命令檢視一下該目錄。
這裡寫圖片描述
可以發現Redis例項裡面有一些持久化檔案,所以我們要把這些持久化檔案刪掉,否則,這個節點中有資料的話,叢集是搭不起來的。
這裡寫圖片描述
接下來,我們通過redis.conf配置檔案來修改redis01例項的執行埠號,將其埠號置為7001,還要記得將redis.conf配置檔案中的cluster-enabled設定為yes喲!
這裡寫圖片描述
redis01例項的配置檔案修改之後,我們只須在redis-cluster目錄下複製5個這樣的Redis例項就可以了,如下圖所示。
這裡寫圖片描述
現在我們有6個Redis例項了,需要把每個Redis例項執行在不同的埠上。redis01這個例項的埠號已經被改為7001了,接下來就是修改其他5個Redis例項的執行埠號了。具體做法是將redis02例項的埠號置為7002,redis03例項的埠號置為7003,redis04例項的埠號置為7004,redis05例項的埠號置為7005,redis06例項的埠號置為7006。

啟動每個Redis例項

我們在一臺虛擬機器上建立好6個Redis例項之後,就需要把每個Redis例項啟動起來。如果想啟動每個Redis例項的話,不必每個例項一個個啟動,這樣太麻煩了,我們可以寫個批處理程式來把它們一下子啟動起來。在redis-cluster目錄下使用vim start-all.sh命令來建立一個批處理檔案,檔案內容為:

cd redis01
./redis-server redis.conf
cd ..
cd redis02
./redis-server redis.conf
cd ..
cd redis03
./redis-server redis.conf
cd ..
cd redis04
./redis-server redis.conf
cd ..
cd redis05
./redis-server redis.conf
cd ..
cd redis06
./redis-server redis.conf
cd ..

儲存完該檔案之後,使用ll命令檢視一下redis-cluster目錄,可以發現start-all.sh檔案,如下圖所示。
這裡寫圖片描述
但是這個批處理程式是不能執行的,所以你使用chmod u+x start-all.sh命令需要改一下它的許可權,這樣我們就可以使用./start-all.sh命令來啟動每個Redis例項了。
這裡寫圖片描述
如何知道每個Redis例項啟動起來了呢?可使用ps aux|grep redis命令來檢視每一個Redis例項的啟動程序,如下圖所示。
這裡寫圖片描述

安裝ruby環境

我們是使用ruby指令碼來搭建叢集的,所以需要安裝ruby的執行環境。具體做法是在聯網的情況下輸入yum install ruby命令來安裝ruby的執行環境,如下圖所示。
這裡寫圖片描述
安裝完ruby之後,我們還需要安裝rubygems(也就是ruby第三方包管理工具),使用命令yum install rubygems,如下圖所示。
這裡寫圖片描述
安裝完ruby和rubygems之後,我們需要安裝ruby指令碼執行所需要的一個包redis-3.0.0.gem,下面是我所下載的redis-3.0.0.gem包。
這裡寫圖片描述
大家下載完後要上傳到虛擬機器上,怎樣知道我們真的上傳上去了呢?在當前使用者主目錄(即root)下使用ll命令檢視一下該目錄即可。
這裡寫圖片描述
下面來安裝這個第三方包,輸入gem install redis-3.0.0.gem命令然後回車,如下圖所示。
這裡寫圖片描述

使用ruby指令碼搭建叢集

上面做了那麼多準備其實是為一個指令碼檔案(redis-trib.rb)服務的,這個指令碼檔案的位置在/root/redis-3.0.0/src目錄下,如下圖所示。
這裡寫圖片描述
為方便管理,我們把這個指令碼檔案複製到/usr/local/redis-cluster目錄下,然後進入到該目錄中,使用ll命令檢視一下該目錄是否有redis-trib.rb指令碼檔案,如下圖所示。
這裡寫圖片描述
下面正式開始搭建叢集,我們使用如下命令來搭建叢集。

./redis-trib.rb create --replicas 1 192.168.25.128:7001 192.168.25.128:7002 192.168.25.128:7003 192.168.25.128:7004 192.168.25.128:7005  192.168.25.128:7006

命令中–replicas是指定每個節點備份的節點的數量,我們現在是每個節點備份一個,因此輸入1。
這裡寫圖片描述
從上圖可以看到從主節點是隨機組成的,主節點是192.168.25.128:7001、192.168.25.128:7002、192.168.25.128:7003這三臺裝置,192.168.25.128:7004、192.168.25.128:7005、192.168.25.128:7006這三臺是備用節點。Adding replica 192.168.25.128:7004 to 192.168.25.128:7001的意思是192.168.25.128:7004作為192.168.25.128:7001的從節點,同理,192.168.25.128:7005作為了192.168.25.128:7002的從節點,192.168.25.128:7006作為了192.168.25.128:7003的從節點。這樣我們的叢集便搭建完了。