Redis集群配置


參考文檔:

  1. redis官網:https://redis.io/
  2. redis集群教程:http://www.redis.cn/topics/cluster-tutorial.html
  3. 單機安裝參考:http://www.runoob.com/redis/redis-install.html
  4. 集群部署參考:http://zyxjohn.blog.51cto.com/5313197/1932714
  5. 配置文件參考:http://www.cnblogs.com/zhoujinyi/p/6430116.html
  6. 集群管理,測試參考:http://www.cnblogs.com/zhoujinyi/p/6477133.html

 本文簡單介紹redis及其集群的配置操作。 

一.環境

1. OS

Server:CentOS-7-x86_64-1511

Node1:10.11.4.201

Node2:10.11.4.202

Node3:10.11.4.203 

2. redis版本

redis-4.0.0:https://redis.io/download

rubygemredis-3.3.3.gem:https://rubygems.org/gems/redis

二.安裝redis服務器

以node1為例,node2/node3配置根據環境微調。

1. 安裝redis

[root@node1 ~]# cd /usr/local/src/
[root@node1 src]# wget http://download.redis.io/releases/redis-4.0.0.tar.gz
[root@node1 src]# tar -zxvf redis-4.0.0.tar.gz
[root@node1 src]# cd redis-4.0.0

#沒有“configure”,直接“make”;
#在安裝的時候指定“PREFIX”,注意不帶“--”,不指定時默認安裝到“/usr/local/bin”下;
#解壓目錄下的“src/“下的二進制文件可直接運行
[root@node1 redis-4.0.0]# make
[root@node1 redis-4.0.0]# make PREFIX=/usr/local/redis install

2. 設置環境變量

#如果是單節點,至此就已安裝完成,可直接啟動;
#啟動指令:”/usr/local/redis/redis-server“,采用默認配置;
#也可在啟動指令后帶”redis.conf”文件指定conf文件;
#”redis.conf”默認文件在解壓目錄下有范本,可直接使用
[root@node1 src]# cd /usr/local/redis/
[root@node1 redis]# ln -s /usr/local/redis/bin/* /usr/local/bin/

3. 配置redis.conf文件

#預設redis運行的pid,log文件,數據等的目錄等
[root@node1 ~]# cd /usr/local/redis/
[root@node1 redis]# mkdir -p /usr/local/redis/etc
[root@node1 redis]# mkdir -pv /usr/local/redis/var/{run,log}
[root@node1 redis]# mkdir -pv /usr/local/redis/var/lib/{redis_6379,redis_6380}

#redis以進程為實例,可以根據每台宿主機的性能與redis的負載運行若干實例,只要區分每個實例的監聽端口即可;
#本實驗每台宿主機運行兩個實例以驗證主從的自動分配;
#以監聽端口重新命名redis.conf文件
[root@node1 redis]# cp /usr/local/src/redis-4.0.0/redis.conf /usr/local/redis/etc/redis_6379.conf

#對於集群配置,以下配置文件中,配置深藍粗體字部分即可,其余可采用默認配置;
#redis.conf文件的詳細配置請參考:http://www.cnblogs.com/zhoujinyi/p/6430116.html
#本宿主機的另一個實例conf文件請參考以上配置修改,可以復制已配置完成的redis_6379.conf為redis_6380.conf后,vim采用“:1,$s/6379/6380/gc”修改。
[root@node1 redis]# vim /usr/local/redis/etc/redis_6379.conf

#監聽地址,這里設置全地址監控;
#開啟/關閉實例的腳本中,關閉實例時調用的是127.0.0.1地址。
bind 0.0.0.0
#監聽端口
port 6379
# 默認沒有在后台執行
daemonize yes # 定義pid與log路徑,根據上文預設配置
pidfile /usr/local/redis/var/run/redis_6379.pid
logfile "/usr/local/redis/var/log/redis_6379.log"

# 集群模式默認是關閉的
cluster-enabled yes # 集群配置文件的名稱,每個節點都有一個集群相關的配置文件,持久化保存集群的信息;
# 此文件不需要手動配置,由Redis生成並更新;
# 每個Redis集群節點/實例需要一個單獨的配置文件,同一宿主機系統中不同實例的配置文件名稱不能沖突
cluster-config-file nodes-6379.conf # 集群節點超時時間,單位毫秒,集群內部多種通信時間限制以此超時時間倍數為准
cluster-node-timeout 15000

#由redis服務器自動生成,默認情況下,redis服務器程序會定期自動對數據庫做一次遍歷,把內存快照寫在一個叫做“dump.rdb”的文件里,這個持久化機制叫做SNAPSHOT;
#有了SNAPSHOT后,如果服務器宕機,重新啟動redis服務器程序時,redis會自動加載dump.rdb,將數據庫狀態恢復到上一次做SNAPSHOT時的狀態
dbfilename "dump.rdb"

#數據目錄,數據庫寫入此目錄,redis 存儲分為內存儲存、磁盤存儲和log文件三部分;
#rdb、aof文件也寫在此目錄;
#rdb持久化可以在指定的時間間隔內生成數據集的時間點快照(point-in-time snapshot);即全量數據(rdb):把內存中的數據寫入磁盤,便於下次讀取文件進行加載
#aof持久化可以記錄服務器執行的所有寫操作命令,並在服務器啟動時,通過重新執行這些命令來還原數據集;aof文件中的命令全部以redis協議的格式來保存,新命令會被追加到文件的末尾;redis 還可以在后台對aof文件進行重寫(rewrite),使得aof文件的體積不會超出保存數據集狀態所需的實際大小;即增量請求(aof):是把內存中的數據序列化為操作請求,用於讀取文件進行replay得到數據
#redis還可以同時使用aof持久化與rdb持久化,此時,當redis重啟時,它會優先使用aof 文件還原數據集,因為aof文件保存的數據集通常比rdb文件所保存的數據集更完整。
dir "/usr/local/redis/var/lib/redis_6379"

4. 配置開機啟動

1)配置啟動腳本

#配置啟動腳本,根據前文的配置文件修改相關參數,可對每個實例分別配置;
#配置啟動腳本主要是方便啟動/關閉服務,不必每次指定redis.conf文件;
#也可通過”redisl-server &”或者”redis-server xxx/redis.conf”等方式啟動服務;
#以下啟動腳本的藍色粗體字體基於默認配置的修改或新增
[root@node1 ~]# cp /usr/local/src/redis-4.0.0/utils/redis_init_script /etc/init.d/redis_6379
[root@node1 ~]# vim /etc/init.d/redis_6379

#!/bin/sh # chkconfig: 35 10 90 #重要!否則chkconfig不能識別開機啟動服務項; #”35”為運行級別,”10”為啟動優先級,”90”為關閉優先級
#
# Simple Redis init.d script conceived to work on Linux systems
# as it does use of the /proc filesystem.

REDISPORT=6379
# EXEC=/usr/local/bin/redis-server
EXEC=/usr/local/redis/bin/redis-server # CLIEXEC=/usr/local/bin/redis-cli
CLIEXEC=/usr/local/redis/bin/redis-cli # PIDFILE=/var/run/redis_${REDISPORT}.pid
PIDFILE=/usr/local/redis/var/run/redis_${REDISPORT}.pid # CONF="/etc/redis/${REDISPORT}.conf"
CONF="/usr/local/redis/etc/redis_${REDISPORT}.conf" USER=redis #添加執行用戶變量

case "$1" in
    start)
        if [ -f $PIDFILE ]
        then
                echo "$PIDFILE exists, process is already running or crashed"
        else
                echo "Starting Redis server..."
                # $EXEC $CONF
                su - $USER -c "$EXEC $CONF" #非root賬號啟動服務
        fi
        ;;
    stop)
        if [ ! -f $PIDFILE ]
        then
                echo "$PIDFILE does not exist, process is not running"
        else
                PID=$(cat $PIDFILE)
                echo "Stopping ..."
                # $CLIEXEC -p $REDISPORT shutdown
                su - $USER -c "$CLIEXEC -p $REDISPORT shutdown" #非root賬號關閉服務
                while [ -x /proc/${PID} ]
                do
                    echo "Waiting for Redis to shutdown ..."
                    sleep 1
                done
                echo "Redis stopped"
        fi
        ;;
 restart|force-reload) ${0} stop ${0} start ;; *) echo "Usage: /etc/init.d/redis {start|stop|restart|force-reload}" >&2 exit 1
Esac

[root@node1 ~]# cp /etc/init.d/redis_6379 /etc/init.d/redis_6380
[root@node1 ~]# vim /etc/init.d/redis_6380
#修改“REDISPORT”變量值
REDISPORT=6380

2)設置開機啟動

[root@node1 ~]# chkconfig --add redis_6379
[root@node1 ~]# chkconfig --level 35 redis_6379 on  #默認runlevel 35已打開
[root@node1 ~]# chkconfig --add redis_6380
[root@node1 ~]# chkconfig --level 35 redis_6380 on

5. 創建賬號並賦權

#因為redis很容易對服務器進行root賬號提取,建議使用非root賬戶啟動redis服務;
#使用創建的賬號執行腳本文件,對服務啟動/關閉,賬號需要有執行shell的權限。
[root@node1 ~]# groupadd redis
[root@node1 ~]# useradd -g redis -s /bin/bash redis
[root@node1 ~]# chown -R redis:redis /usr/local/redis
[root@node1 ~]# chown redis:redis /etc/init.d/redis_6379
[root@node1 ~]# chown redis:redis /etc/init.d/redis_6380
[root@node1 ~]# chmod +x /etc/init.d/redis_6379       #默認有執行權限,可不設置
[root@node1 ~]# chmod +x /etc/init.d/redis_6380

6. 設置iptables

[root@node1 ~]# vim /etc/sysconfig/iptables
-A INPUT -p tcp -m state --state NEW -m tcp --dport 6379 -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 6380 -j ACCEPT

[root@node1 ~]# service iptables restart

7. 啟動

#可通過啟動腳本啟動/關閉服務;或采用”service”指令
[root@node1 ~]# su - redis -c "/etc/init.d/redis_6379 start"
[root@node1 ~]# su - redis -c "/etc/init.d/redis_6380 start"

8. 驗證

[root@node1 ~]# ps aux | grep redis            #注意啟動賬戶
[root@node1 ~]# netstat -tunlp | grep redis

三.配置redis cluster

Redis 3.0之后,官方版本支持了Cluster,與之前的第三方cluster相比(如Twenproxy、Codis),Redis Cluster沒有使用Porxy的模式來連接集群節點,而是使用無中心節點的模式來組建集群。

在Cluster出現之前,只有Sentinel保證了Redis的高可用性。

Redis Cluster在多個節點之間進行數據共享,即使部分節點失效或無法進行通訊時,Cluster仍然可以繼續處理請求。

如果每個主節點都有一個從節點支持,在主節點下線或無法與集群的大多數節點進行通訊的情況下,從節點提升為主節點,並提供服務,保證Cluster正常運行。

Redis Cluster的節點分片是通過哈希槽(hash slot)實現的,每個鍵都屬於這 16384(0~16383) 個哈希槽的其中一個,每個節點負責處理一部分哈希槽。

1. 配置集群管理工具

#redis作者基於ruby寫了集群管理工具,首先安裝ruby相關依賴。
[root@node1 ~]# yum install ruby rubygems -y
[root@node1 ~]# cd /usr/local/src/ 
[root@node1 src]# wget https://rubygems.org/downloads/redis-3.3.3.gem
[root@node1 src]# gem install redis-3.3.3.gem

#集群管理工具redis-trib.rb在解壓包中已包含;
#redis-trib.rb是基於ruby的集群管理工具,如果不使用此工具,也可以手工創建集群,具體操作請見:http://www.cnblogs.com/zhoujinyi/p/6477133.html
[root@node1 src]# cp /usr/local/src/redis-4.0.0/src/redis-trib.rb /usr/local/redis/bin/
[root@node1 src]# ln -s /usr/local/redis/bin/redis-trib.rb /usr/local/bin/

redis-trib.rb具有以下功能:
1) create:創建集群
2) check:檢查集群
3) info:查看集群/節點信息
4) fix:修復集群
5) reshard:在線遷移slot
6) rebalance:平衡集群節點slot數量
7) add-node:將新節點加入集群
8) del-node:從集群中刪除節點
9) set-timeout:設置集群節點間心跳連接的超時時間
10) call:在集群全部節點上執行命令
11) import:將外部redis數據導入集群

 

2. 創建集群

1)創建集群

[root@node1 ~]# redis-trib.rb create --replicas 1 10.11.4.201:6379 10.11.4.201:6380 10.11.4.202:6379 10.11.4.202:6380 10.11.4.203:6379 10.11.4.203:6380 
  • 節點已自動分配主從關系,且主節點分布在不同的宿主機上,10.11.4.201與10.11.4.202節點上的實例互為主從,但10.11.4.203上的兩個實例互為主從有一定的風險

  •  同意分配計划,輸入"yes"后,各節點開始通訊,並協商哈希槽的分配,最后輸出報告指出各主節點分配的哈希槽,16384個哈希槽全部分配完畢,集群創建成功。

2)注意事項 

  • (1) "--replicas 1"參數,指定每個主節點配置的從節點數量,如果這里設置為1,最少3個主節點的情況下,總節點數不能低於6,否則集群不能成功創建; 
  • (2) 加入集群的節點必須是空節點,不包含槽/數據信息,否則不能加入集群,報錯如下:

    [ERR] Node 10.11.4.201:6379 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.

    解決方案如下:

    1. 停止redis服務;
    2. 刪除相關或全部節點的appendonly.aof,dump.rdb,nodes.conf文件;
    3. 一般執行上面兩步即可,如果還不行可執行清庫操作
    • [root@node1 ~]# redis-cli -c -p 6379
      127.0.0.1:6379> flushdb

  • (3) 在同意集群分配方案,輸入"yes"后,進行到"Waiting for the cluster to join"階段,但一直處於等待狀態,無報錯,現象如下:

    原因:redis集群除提供給客戶端連接的端口外,還有集群通訊的"集群總線端口",此端口為客戶端連接端口+10000,這里即為:16379/16380

    解決方案如下

    1. iptables放行相關端口或關閉iptables服務。

3)集群創建流程

  • (1) 為每個節點創建ClusterNode對象,包括連接每個節點,檢查每個節點是否為獨立且db為空的節點,執行load_info方法導入節點信息。
  • (2) 檢查傳入的master節點數量是否大於等於3個,只有大於3個節點才能組成集群。
  • (3) 計算每個master需要分配的slot數量,同時為master分配slave,分配的算法大致如下:
    • (a) 將節點按host分類,這樣保證master節點能分配到更多的主機中。
    • (b) 不停遍歷host列表,從每個host列表中彈出一個節點,放入interleaved數組,直到所有的節點都彈出為止;master節點列表就是interleaved前面的master數量的節點列表,保存為masters數組。
    • (c) 計算每個master節點負責的slot數量,保存在slots_per_node對象,用slot總數除以master數量取整即可。
    • (d) 遍歷masters數組,每個master分配slots_per_node個slot,最后一個master,分配到16384個slot為止。
    • (e) 為master分配slave,分配算法會盡量保證master和slave節點不在同一台主機上;對於分配完指定slave數量的節點,如果還有多余的節點,也會為這些節點尋找master。

      分配算法會遍歷兩次masters數組:第一次遍歷masters數組,在余下的節點列表找到replicas數量個slave,每個slave為第一個和master節點host不一樣的節點,如果沒有不一樣的節點,則直接取出余下列表的第一個節點;第二次遍歷是在對於節點數除以replicas不為整數,則會多余一部分節點,遍歷的方式跟第一次一樣,只是第一次會一次性給master分配replicas數量個slave,而第二次遍歷只分配一個,直到余下的節點被全部分配出去。

  • (4) 打印出分配信息,確認是否按照給出分配方式創建集群。
  • (5) 輸入"yes"同意后,執行flush_nodes_config操作,該操作執行前面的分配結果,給master分配slot,讓slave復制master;對於還沒有握手(cluster meet)的節點,slave復制操作無法完成,但flush_nodes_config操作出現異常會很快返回,后續握手后會再次執行flush_nodes_config。
  • (6) 為每個節點分配epoch,遍歷節點,每個節點分配的epoch比之前節點大1。
  • (7) 節點間開始相互握手,握手的方式為節點列表的其他節點與第一個節點握手。
  • (8) 然后每隔1秒檢查一次各節點是否已經消息同步完成,使用ClusterNode的get_config_signature方法,檢查的算法為獲取每個節點cluster nodes信息,排序每個節點,組裝成node_id1:slots|node_id2:slot2|...的字符串,如果每節點獲得字符串都相同,即認為握手成功。
  • (9) 再執行一次flush_nodes_config,這次主要是為了完成slave復制操作。
  • (10) 最后再執行check_cluster,全面檢查一次集群狀態;包括和前面握手時檢查一樣的方式再檢查一遍,確認沒有遷移的節點,確認所有的slot都被分配出去了。
  • (11) 至此完成了整個創建流程,返回"[OK] All 16384 slots covered."。

四.驗證

1. 集群檢查

1)redus-trib.rb

#首先列出檢查點的狀態信息,節點10.11.4.203:6379是主節點,分配的哈希槽是10923~16383,有1個從節點運行;
#其他節點的信息也會列出,最后檢查哈希槽的分配狀態;
#“redis-trib.rb info 10.11.4.201:6379”可以查看單節點信息
[root@node1 ~]# redis-trib.rb check 10.11.4.203:6379

2)CLUSTER命令

#”cluster info”,列出集群狀態,16384個哈希槽已全部分配等;
#”cluster nodes”,分別列出每個節點的集群id,狀態等。
[root@node1 ~]# redis-cli -c -h 10.11.4.202 -p 6379
10.11.4.202:6379> cluster info
10.11.4.202:6379> cluster nodes

#”cluster slots”可以查看槽位與對應節點的信息
[root@node1 ~]# redis-cli -c -h 10.11.4.202 -p 6379
10.11.4.202:6379> cluster slots

2. 數據測試

具體數據測試,failover可參考:http://www.cnblogs.com/zhoujinyi/p/6477133.html

1)Key-Value建立與查詢

[root@node1 ~]# redis-cli -c -h 10.11.4.202 -p 6379
10.11.4.202:6379> set test world
10.11.4.202:6379> get test
10.11.4.202:6379> exit

#在節點10.11.4.203:6379上獲取key值”test”,會有一個重定向動作,將”test”的value指向6918哈希槽,在10.11.4.202:6379節點上
[root@node1 ~]# redis-cli -c -h 10.11.4.203 -p 6379
10.11.4.203:6379> get test

#”cluster countkeysinslot XXX”可以獲取指定哈希槽的key的數量
[root@node1 ~]# redis-cli -c -h 10.11.4.202 -p 6379
10.11.4.202:6379> cluster countkeysinslot 6918

2)在線遷移

#在線遷移可用於將集群中的一些slot從源節點遷移到目的節點,如完成集群的在線橫向擴容或縮容。
[root@node1 ~]# redis-trib.rb reshard 10.11.4.202:6379
#遷移槽位數量
How many slots do you want to move (from 1 to 16384)? 1
#遷移目的節點
What is the receiving node ID? 20a918f42f6dbad7feb1d4bbf19d9895c06db691 #遷移源節點
Source node #1:f7fcd0b8170c316c37a947cbfd5a654f9fb582e0
Source node #2:done
#遷移計划執行與否
Do you want to proceed with the proposed reshard plan (yes/no)? yes

#哈希槽5461已從10.11.4.202節點遷移到10.11.4.203節點;
#遷移后,哈希槽分布不均,可采用redis-trib.rb的“rebalance”進行平衡
[root@node1 ~]# redis-cli -c -h 10.11.4.203 -p 6379
10.11.4.203:6379> cluster nodes


免責聲明!

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



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