【Redis】集羣方式

1、概述

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. 使用一些代理工具

2、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的投票機制,具體原理以下圖所示:

15560920746015155609

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

3、搭建集羣方案

3.1 準備工做

  • 安裝部署任何一個應用其實都很簡單,只要安裝步驟一步一步來就好了。下面說一下 Redis 集羣搭建規劃,因爲集羣至少須要6個節點(3主3從模式),因此,若是沒有這麼多機器,本地也起不了那麼多虛擬機(電腦太爛),如今計劃是在一臺機器上模擬一個集羣,固然,這和生產環境的集羣搭建沒本質區別。html

  1. 安裝一個Linux虛擬機,開啓Linux,鏈接Linux
  2. 先關閉防火牆
  3. 而後安裝純淨版本的redis Redis安裝
  4. 修改redis.conf 文件 將 bind 改成當前Linux服務器的ip地址
  5. 並將redis改成後臺啓動。

3.2 建立模擬集羣的文件夾

咱們計劃集羣中 Redis 節點的端口號爲 9001-9006 ,端口號即集羣下各實例文件夾。數據存放在 端口號/data 文件夾中。node

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 路徑下的運行腳本拷貝過來。看命令:git

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 中的全部和端口的相關的信息便可,其實就那麼四個位置。開始操做:github

\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 文件

其實很是簡單了,你經過搜索會發現其實只有四個點須要修改,咱們全局替換下吧,進入相應的節點文件夾,作替換就行了。命令很是簡單:redis

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

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

(error) CLUSTERDOWN Hash slot not served

  這是由於雖然咱們配置並啓動了 Redis 集羣服務,可是他們暫時還並不在一個集羣中,互相直接發現不了,並且尚未可存儲的位置,就是所謂的slot(槽)。shell

3.9 安裝集羣所需軟件

##因爲 Redis 集羣須要使用 ruby 命令,因此咱們須要安裝 ruby 和相關接口。
yum install ruby
yum install rubygems
gem install redis ##執行此行命令會報錯, 要使用本地上傳方式

下載地址安裝包GitHubvim

從本地上傳到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
###擴展註冊方式 代碼獲取到配置文件 靈活該密碼

4、Redis集羣的幾個注意事項

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

5、集羣事務

Redis集羣默圦是不支持亊各,可是亊各能夠在単獨節點上能夠支持 寫插件Redis+Lua

相關文章
相關標籤/搜索