【Redis】集群方式


一、概述

1.1 Redis3.0版本之前

  1. 3.0版本之前的redis是不支持集群的,我們的redis如果想要集群的話,就需要一個中間件,然后這個中間件負責將我們需要存入redis中的數據的key通過一套算法計算得出一個值。然后根據這個值找到對應的redis節點,將這些數據存在這個redis的節點中。
  2. 在取值的時候,同樣先將key進行計算,得到對應的值,然后就去找對應的redis節點,從對應的節點中取出對應的值。
  3. 這樣做有很多不好的地方,比如說我們的這些計算都需要在系統中去進行,所以會增加系統的負擔。還有就是這種集群模式下,某個節點掛掉,其他的節點無法知道。而且也不容易對每個節點進行負載均衡。

1.2 常見集群方案

  1. 官方方案:redis-cluster(強烈推薦),3.0之后開始實現
  2. 客戶端分片技術(不推薦),擴容/縮容時,必須手動調整分片程序,出現故障不能自動轉移
  3. 可以使用主從復制方式(不推薦):數據非常冗余,浪費內存
  4. 使用一些代理工具

二、Redis-Cluster原理

  • Redis 是一個開源的 key-value 存儲系統,由於出眾的性能,大部分互聯網企業都用來做服務器端緩存。Redis 在3.0版本前只支持單實例模式,雖然支持主從模式、哨兵模式部署來解決單點故障,但是現在互聯網企業動輒大幾百G的數據,可完全是沒法滿足業務的需求,所以,Redis 在 3.0 版本以后就推出了集群模式。
  • Redis 集群采用了P2P的模式,完全去中心化。Redis 把所有的 Key 分成了 16384 個 slot,每個 Redis 實例負責其中一部分 slot 。集群中的
  • 所有信息(節點、端口、slot等),都通過節點之間定期的數據交換而更新。
  • Redis 客戶端可以在任意一個 Redis 實例發出請求,如果所需數據不在該實例中,通過重定向命令引導客戶端訪問所需的實例。

原理圖
原理圖

原理圖
原理圖

  • 在這個圖中,每一個藍色的圈都代表着一個redis的服務器節點。它們任何兩個節點之間都是相互連通的。客戶端可以與任何一個節點相連接,然后就可以訪問集群中的任何一個節點。對其進行存取和其他操作。
  • 那么redis是怎么做到的呢?首先,在redis的每一個節點上,都有這么兩個東西,一個是插槽(slot)可以理解為是一個可以存儲兩個數值的一個變量這個變量的取值范圍是:0-16383。還有一個就是cluster我個人把這個cluster理解為是一個集群管理的插件。當我們的存取的key到達的時候,redis會根據crc16的算法得出一個結果,然后把結果對 16384 求余數,這樣每個 key 都會對應一個編號在 0-16383 之間的哈希槽,通過這個值,去找到對應的插槽所對應的節點,然后直接自動跳轉到這個對應的節點上進行存取操作。
  • 還有就是因為如果集群的話,是有好多個redis一起工作的,那么,就需要這個集群不是那么容易掛掉,所以呢,理論上就應該給集群中的每個節點至少一個備用的redis服務。這個備用的redis稱為從節點(slave)。那么這個集群是如何判斷是否有某個節點掛掉了呢?
  • 首先要說的是,每一個節點都存有這個集群所有主節點以及從節點的信息。
  • 它們之間通過互相的ping-pong判斷是否節點可以連接上。如果有一半以上的節點去ping一個節點的時候沒有回應,集群就認為這個節點宕機了,然后去連接它的備用節點。如果某個節點和所有從節點全部掛掉,我們集群就進入faill狀態。還有就是如果有一半以上的主節點宕機,那么我們集群同樣進入發力了狀態。這就是我們的redis的投票機制,具體原理如下圖所示:

15560920746015
155609

  • 這套架構的特點:
    • 分片算法:基於 slot hash桶;
    • 分片實例之間相互獨立,每組 一個master 實例和多個slave;
    • 路由信息存放到第三方存儲組件,如 zookeeper 或etcd
    • 旁路組件探活

三、搭建集群方案

3.1 准備工作

  • 安裝部署任何一個應用其實都很簡單,只要安裝步驟一步一步來就行了。下面說一下 Redis 集群搭建規划,由於集群至少需要6個節點(3主3從模式),所以,如果沒有這么多機器,本地也起不了那么多虛擬機(電腦太爛),現在計划是在一台機器上模擬一個集群,當然,這和生產環境的集群搭建沒本質區別。

  1. 安裝一個Linux虛擬機,開啟Linux,連接Linux
  2. 先關閉防火牆
  3. 然后安裝純凈版本的redis Redis安裝
  4. 修改redis.conf 文件 將 bind 改為當前Linux服務器的ip地址
  5. 並將redis改為后台啟動。

3.2 創建模擬集群的文件夾

我們計划集群中 Redis 節點的端口號為 9001-9006 ,端口號即集群下各實例文件夾。數據存放在 端口號/data 文件夾中。

mkdir /usr/local/redis-cluster
cd redis-cluster/
mkdir -p 9001/data 9002/data 9003/data 9004/data 9005/data 9006/data

3.3 復制腳本

  在 /usr/local/redis-cluster 下創建 bin 文件夾,用來存放集群運行腳本,並把安裝好的 Redis 的 src 路徑下的運行腳本拷貝過來。看命令:

cd /usr/local/redis-cluster
mkdir bin    
cd /usr/local/redis-3.2.9/src
cp mkreleasehdr.sh redis-benchmark redis-check-aof  redis-cli redis-server redis-trib.rb /usr/local/redis-cluster/bin    

3.4 復制一個新 Redis 實例

##我們現在從已安裝好的 Redis 中復制一個新的實例到 9001 文件夾,並修改 redis.conf 配置。

cp -r /usr/local/redis    /usr/local/redis-cluster/9001
    
##注意,修改 redis.conf 配置和單點唯一區別是下面部分,其余還是常規的這幾項:
port 9001(每個節點的端口號)
daemonize yes
bind 192.168.140.137(綁定當前機器 IP)
dir /usr/local/redis-cluster/9001/data/(數據文件存放位置)
pidfile /var/run/redis_9001.pid(pid 9001和port要對應)
cluster-enabled yes(啟動集群模式)
cluster-config-file nodes-9001.conf(9001和port要對應)
cluster-node-timeout 15000
appendonly yes

3.5 再復制出五個新 Redis 實例

  我們已經完成了一個節點了,其實接下來就是機械化的再完成另外五個節點,其實可以這么做:把 9001 實例 復制到另外五個文件夾中,唯一要修改的就是 redis.conf 中的所有和端口的相關的信息即可,其實就那么四個位置。開始操作:

\cp -rf /usr/local/redis-cluster/9001/*   /usr/local/redis-cluster/9002
\cp -rf /usr/local/redis-cluster/9001/*   /usr/local/redis-cluster/9003
\cp -rf /usr/local/redis-cluster/9001/*   /usr/local/redis-cluster/9004
\cp -rf /usr/local/redis-cluster/9001/*   /usr/local/redis-cluster/9005
\cp -rf /usr/local/redis-cluster/9001/*   /usr/local/redis-cluster/9006
    
## \cp -rf 命令是不使用別名來復制,因為 cp 其實是別名 cp -i,操作時會有交互式確認,比較煩人。

3.6 修改 9002-9006 的 redis.conf 文件

其實非常簡單了,你通過搜索會發現其實只有四個點需要修改,我們全局替換下吧,進入相應的節點文件夾,做替換就好了。命令非常簡單:

vim /usr/local/redis-cluster/9002/redis/etc/redis.conf   
vim /usr/local/redis-cluster/9003/redis/etc/redis.conf
vim /usr/local/redis-cluster/9004/redis/etc/redis.conf
vim /usr/local/redis-cluster/9005/redis/etc/redis.conf
vim /usr/local/redis-cluster/9006/redis/etc/redis.conf
      
:%s/9001/9002
:%s/9001/9003
:%s/9001/9004
:%s/9001/9005
:%s/9001/9006
    
    
## 其實我們也就是替換了下面這四行:
    
port 9002
dir /usr/local/redis-cluster/9002/data/
cluster-config-file nodes-9002.conf
pidfile /var/run/redis_9002.pid

3.7 啟動9001-9006六個節點

##這里用了/usr/local/redis/bin/ 目錄下的redis服務啟動的,
## 也可以使用9001各個目錄下的redis服務分別啟動

/usr/local/redis/bin/redis-server  /usr/local/redis-cluster/9001/redis/etc/redis.conf
/usr/local/redis/bin/redis-server  /usr/local/redis-cluster/9002/redis/etc/redis.conf
/usr/local/redis/bin/redis-server  /usr/local/redis-cluster/9003/redis/etc/redis.conf
/usr/local/redis/bin/redis-server  /usr/local/redis-cluster/9004/redis/etc/redis.conf
/usr/local/redis/bin/redis-server  /usr/local/redis-cluster/9005/redis/etc/redis.conf
/usr/local/redis/bin/redis-server  /usr/local/redis-cluster/9006/redis/etc/redis.conf

啟動成功看下圖:

3.8 隨便找一個節點測試試

/usr/local/redis-cluster/9001/redis/bin/redis-cli -c -h 192.168.140.137  -p 9001

**添加數據是會報錯: **

 (error) CLUSTERDOWN Hash slot not served

  這是因為雖然我們配置並啟動了 Redis 集群服務,但是他們暫時還並不在一個集群中,互相直接發現不了,而且還沒有可存儲的位置,就是所謂的slot(槽)。

3.9 安裝集群所需軟件

##由於 Redis 集群需要使用 ruby 命令,所以我們需要安裝 ruby 和相關接口。
yum install ruby
yum install rubygems
gem install redis ##執行此行命令會報錯, 要使用本地上傳方式

下載地址安裝包GitHub

從本地上傳到Linux
將此文件拖到usr/local目錄下

文件上傳到Linux中后 進入/usr/local/到執行下面的命令

gem install -l redis-3.2.1.gem

3.10集群環境測試

/usr/local/redis-cluster/bin/redis-trib.rb create --replicas 1 192.168.140.137:9001 192.168.140.137:9002 192.168.140.137:9003 192.168.140.137:9004 192.168.140.137:9005 192.168.140.137:9006

執行效果如下,發現有三主三備:

  目前來看,9001-9003 為主節點,9004-9006 為從節點,並向你確認是否同意這么配置。輸入 yes 后,會開始集群創建。

  • 簡單解釋一下這個命令:調用 ruby 命令來進行創建集群,--replicas 1 表示主從復制比例為 1:1,即一個主節點對應一個從節點;然后,默認給我們分配好了每個主節點和對應從節點服務,以及 solt 的大小,因為在 Redis 集群中有且僅有 16383 個 solt ,默認情況會給我們平均分配,當然你可以指定,后續的增減節點也可以重新分配。
M: fbec3c1091ff20adbabf8d144043cc3abae9a7f9  ##為主節點Id
    
S: 09726b68f4a1c849e8e188bd45d506aed17fd970 192.168.140.137:9004
slots: (0 slots) slave
replicates fbec3c1091ff20adbabf8d144043cc3abae9a7f9 ##從節點下對應主節點Id

3.11 驗證集群環境

## 這里要輸入-c,表示集群環境
/usr/local/redis-cluster/9001/redis/bin/redis-cli -c -h 192.168.140.137  -p 9001 
set name 123456 ## 會發現它自動跳轉到9002redis上面

3.12 SpringBoot整合Redis集群

spring:
  redis:
    database: 0
#    host: 132.168.44.127
#    port: 6379
#    password: 123456
    jedis:
      pool:
        max-active: 8
        max-wait: -1
        max-idle: 8
        min-idle: 0
    timeout: 10000
    cluster:
      nodes:
        - 192.168.140.137:9001
        - 192.168.140.137:9002
        - 192.168.140.137:9003
        - 192.168.140.137:9004
        - 192.168.140.137:9005
        - 192.168.140.137:9006
###擴展注冊方式 代碼獲取到配置文件 靈活該密碼   
    

四、Redis集群的幾個注意事項

  • Redis集群使用CRC16對key進行hash,集群固定使用16384對hash出來的值取模。因為取模結果一定在16384之內,所以集群中的sharding(分片)實際就是如何將16384個值在n個主節點間分配(從節點是主節點的近似副本,原因見3),如何分配取決於你的配置。
  • Redis生產級集群需要容災,為此,一般部署為n個主+n*m個從。n大小主要取決於單機性能,m大小主要取決於機器穩定性。
  • Redis集群是弱一致性的,此處的一致,主要指主從之間的數據一致性。主要是因為redis在做數據更新時,不要求主從數據同步復制一定要成功。
  • 集群最小的主數量為3,主數量應為奇數,以便做選舉判決。

五、集群事務

Redis集群默圦是不支持亊各,但是亊各可以在単獨節點上可以支持
寫插件Redis+Lua


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM