Redis 高級(主從,哨兵,集群)

一、主從復(fù)制

image

Redis 的主從復(fù)制特點

image

1. 配置主從

實現(xiàn)方式同樣有兩種: 命令方式和配置文件方式

命令方式

只需要在從服務(wù)器上執(zhí)行如下命令即可

slaveof  主服務(wù)器的IP  端口號

slaveof 命令是異步的,不阻塞。
并且此時,從服務(wù)器現(xiàn)有的數(shù)據(jù)會先被清空,之后再同步主服務(wù)器的數(shù)據(jù)。

停止一臺從服務(wù)器的復(fù)制操作,在此臺服務(wù)器上執(zhí)行如下命令

slaveof no   one

配置文件的方式如下

只需要在從服務(wù)器上配置即可

修改配置文件
假如主服務(wù)器 IP 是: 172.16.153.178
端口是: 6379

# slaveof <masterip> <masterport>
slaveof  172.16.153.178 6379

// 配置此服務(wù)器只提供讀取操作
slave-read-only yes

之后重啟從主機的 Redis 服務(wù)

查看主從信息

127.0.0.1:6379> info  replication

二、主從 + Sentinel 哨兵模式

Redis Sentinel是Redis官方的高可用性解決方案。

Redis 的 Sentinel 系統(tǒng)用于管理多個 Redis 服務(wù)器(instance), 該系統(tǒng)執(zhí)行以下三個任務(wù):

  • 監(jiān)控(Monitoring): Sentinel 會不斷地檢查你的主服務(wù)器和從服務(wù)器是否運作正常。

  • 提醒(Notification): 當被監(jiān)控的某個 Redis 服務(wù)器出現(xiàn)問題時, Sentinel 可以通過 API 向管理員或者其他應(yīng)用程序發(fā)送通知。

  • 自動故障遷移(Automatic failover): 當一個主服務(wù)器不能正常工作時, Sentinel 會開始一次自動故障遷移操作, 它會將失效主服務(wù)器的其中一個從服務(wù)器升級為新的主服務(wù)器, 并讓失效主服務(wù)器的其他從服務(wù)器改為復(fù)制新的主服務(wù)器; 當客戶端試圖連接失效的主服務(wù)器時, 集群也會向客戶端返回新主服務(wù)器的地址, 使得集群可以使用新主服務(wù)器代替失效服務(wù)器。

Redis Sentinel 是一個分布式系統(tǒng), 你可以在一個架構(gòu)中運行多個 Sentinel 進程(progress), 這些進程使用流言協(xié)議(gossip protocols)來接收關(guān)于主服務(wù)器是否下線的信息, 并使用投票協(xié)議(agreement protocols)來決定是否執(zhí)行自動故障遷移, 以及選擇哪個從服務(wù)器作為新的主服務(wù)器。

雖然 Redis Sentinel 釋出為一個單獨的可執(zhí)行文件 redis-sentinel , 但實際上它只是一個運行在特殊模式下的 Redis 服務(wù)器。

此種模式下,客戶端要訪問的 服務(wù) IP 不是主節(jié)點,而是 sentiner 服務(wù)器的 IP。

架構(gòu)圖

image

Redis Sentinel 故障轉(zhuǎn)移

image

架構(gòu)的擴展應(yīng)用

image

1. 配置主從

a. 快速生成主節(jié)點的配置文件

編譯全新文件 /etc/redis/redis-6380.conf, 添加如下內(nèi)容

port 6380
daemonize yes
protected-mode no
pidfile /var/run/redis-6380.pid
logfile /var/log/redis-6380.log
dir /redis/data/

假如是多個主機實現(xiàn)的,就需要更改為 protected-mode yes,
并且添加 bind 0.0.0.0

b. 快速生成從節(jié)點的配置文件

[root@s1 ~]# sed 's/6380/6381/g' /etc/redis/redis-6380.conf > /etc/redis/redis-6381.conf
[root@s1 ~]# sed 's/6380/6382/g' /etc/redis/redis-6380.conf > /etc/redis/redis-6382.conf

查看配置文件內(nèi)容,檢驗配置結(jié)果

[root@s1 ~]# cat /etc/redis/redis-6381.conf
port 6381
daemonize yes
pidfile /var/run/redis-6381.pid
logfile /var/log/redis-6381.log
dir /redis/data/
[root@s1 ~]# cat /etc/redis/redis-6382.conf
port 6382
daemonize yes
pidfile /var/run/redis-6382.pid
logfile /var/log/redis-6382.log
dir /redis/data/
[root@s1 ~]#

c. 配置主從關(guān)系

[root@s1 ~]# echo "slaveof  172.16.153.178 6380" >> /etc/redis/redis-6381.conf
[root@s1 ~]# echo "slaveof  172.16.153.178 6380" >> /etc/redis/redis-6382.conf
[root@s1 ~]#

d. 啟動服務(wù),并驗證進程

[root@s1 ~]# /usr/local/bin/redis-server /etc/redis/redis-6380.conf
[root@s1 ~]# /usr/local/bin/redis-server /etc/redis/redis-6381.conf
[root@s1 ~]# /usr/local/bin/redis-server /etc/redis/redis-6382.conf
[root@s1 ~]# ps -ef |grep redis
root       4335      1  0 19:30 ?        00:00:03 /usr/local/bin/redis-server *:6380
root       4490      1  0 20:17 ?        00:00:00 /usr/local/bin/redis-server *:6381
root       4495      1  0 20:17 ?        00:00:00 /usr/local/bin/redis-server *:6382
root       4500   3755  0 20:17 pts/0    00:00:00 grep --color=auto redis
[root@s1 ~]#

假如日志中出現(xiàn)如下警告信息

4668:S 17 Feb 20:28:42.107 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
4668:S 17 Feb 20:28:42.107 # Server initialized
4668:S 17 Feb 20:28:42.108 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
4668:S 17 Feb 20:28:42.108 * DB loaded from disk: 0.000 seconds
4668:S 17 Feb 20:28:42.110 * Before turning into a slave, using my master parameters to sy

解決辦法
The TCP backlog...
方法1: 臨時設(shè)置生效:
shell> sysctl -w net.core.somaxconn=1024

方法2: 永久生效:
修改/etc/sysctl.conf文件,增加一行
net.core.somaxconn=1024

然后執(zhí)行命令
sysctl -p

WARNING overcommit_memory ...
方法1: 臨時設(shè)置生效:
shell> sysctl -w vm.overcommit_memory=1

方法2: 永久生效:
修改/etc/sysctl.conf文件,增加一行
vm.overcommit_memory=1

然后執(zhí)行命令
sysctl -p

e. 查看主從復(fù)制信息

image

2. 配置 sentinel

獲取程序

Sentinel 程序可以在編譯后的 src 文檔中發(fā)現(xiàn), 它是一個命名為 redis-sentinel 的程序。

運行一個 Sentinel 所需的最少配置如下所示:

Redis 源碼中包含了一個名為 sentinel.conf 的文件, 這個文件是一個帶有詳細注釋的 Sentinel 配置文件示例。

運行一個 Sentinel 所需的最少配置如下所示:

// 監(jiān)控一個 Redis 服務(wù)器
// 名稱為 mymaster ,IP 為 127.0.0.1 端口為 6379
// 最后的 2  是指最少有 2 給 Sentinel 實例同意一臺 redis 服務(wù)器宕機,才會認為 客觀下線。
// sentinel monitor  自定義的主節(jié)點名稱 主節(jié)點的 IP  主節(jié)點端口   票數(shù) 

sentinel monitor mymaster 127.0.0.1 6379 2

sentinel down-after-milliseconds mymaster 3000

// 180 秒后開始故障自動裝換
sentinel failover-timeout mymaster 5000

sentinel parallel-syncs mymaster 1

各個選項的功能如下:

down-after-milliseconds 選項指定了 Sentinel 認為服務(wù)器已經(jīng)斷線所需的毫秒數(shù)。
如果服務(wù)器在給定的毫秒數(shù)之內(nèi), 沒有返回 Sentinel 發(fā)送的 PING 命令的回復(fù), 或者返回一個錯誤, 那么 Sentinel 將這個服務(wù)器標記為主觀下線(subjectively down,簡稱 SDOWN )。

不過只有一個 Sentinel 將服務(wù)器標記為主觀下線并不一定會引起服務(wù)器的自動故障遷移: 只有在足夠數(shù)量的 Sentinel 都將一個服務(wù)器標記為主觀下線之后, 服務(wù)器才會被標記為客觀下線(objectively down, 簡稱 ODOWN ), 這時自動故障遷移才會執(zhí)行。

將服務(wù)器標記為客觀下線所需的 Sentinel 數(shù)量由對主服務(wù)器的配置決定。

parallel-syncs 選項指定了在執(zhí)行故障轉(zhuǎn)移時, 最多可以有多少個從服務(wù)器同時對新的主服務(wù)器進行同步, 這個數(shù)字越小, 完成故障轉(zhuǎn)移所需的時間就越長。

哨兵的領(lǐng)導(dǎo)者選舉

票數(shù)和領(lǐng)導(dǎo)者選舉有關(guān)系

領(lǐng)導(dǎo)者選舉的事件發(fā)生,必須滿足下面的條件

max(票數(shù), (哨兵的個數(shù) / 2) + 1 ) 個哨兵參加選舉

才可以選舉出領(lǐng)導(dǎo)者,從而完成故障轉(zhuǎn)移。

比如有 5 個哨兵, 配置的票數(shù)是 4

max(4, (5 / 2) + 1)

max(4, 3.5)
4 最大
結(jié)果就是需要 4 個哨兵參與選舉才可以。

a. 獲取并修改配置文件

快速創(chuàng)建三個 sentinel 配置文件
進入到 Redis 源碼的目錄下,執(zhí)行如下命令

image

修改監(jiān)聽端口

image

之后在每個 sentinel 配置文件中添加守護進程方式運行,
并修改dir 配置項的目錄,

daemonize yes
dir /redis/data/
logfile  "sentinel-${port}.log"

最后別忘了修改監(jiān)控的主服務(wù)器的 IP 和端口正確的 6380

最終其中一個的配置文件應(yīng)該是這樣的

image

b. 啟動服務(wù)并驗證

啟動服務(wù)的語法:

shell> redis-sentinel   sentinel的配置文件

image
image

可以使用以下命令查看哨兵的信息

[root@s1 ~]# redis-cli -p 27001 info
...略...
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=127.0.0.1:6380,slaves=2,sentinels=3
[root@s1 ~]#

3. 客戶端如何連接使用 Sentinel

客戶端需要知道所有 Sentinel 所有節(jié)點的 IP和一個 Master Name。

第一步從所有的 Sentinel 列表中得到一個有效的 Sentinel 節(jié)點。

image

第二步向得到的 Sentinel 節(jié)點發(fā)送查詢一個已知的 Master Name 的信息到請求,并得到 Master 節(jié)點的信息

image

第三步向 Master 節(jié)點驗證 Maset 角色的真實性

image

第四步 客戶端 和 Sentiel 之間建立發(fā)布訂閱關(guān)系。

客戶端訂閱 Sentinel 的頻道,一旦 Master 的 IP 信息有變化,客戶端就會通過此頻道發(fā)布的信息得知。

image

4. 故障演練

停止 Master 節(jié)點的服務(wù)

[root@s1 ~]# redis-cli -p 6380 shutdown

不斷的刷新其中一個 Sentinel 節(jié)點的信息,觀察最后一行信息的變化

[root@s1 ~]# redis-cli -p 27001 info
...略...
master0:name=mymaster,status=ok,address=127.0.0.1:6382,slaves=2,sentinels=3



三、 集群

1. 數(shù)據(jù)分區(qū)介紹

image

a. 數(shù)據(jù)分區(qū)的方式

image

兩者的對比

image

b. 哈希分區(qū)的三種方式

  • 節(jié)點取余

  • 一致性哈希

  • 虛擬槽哈希

① 節(jié)點取余(不推薦使用)

image
問題: 當向集群重添加一個節(jié)點時,數(shù)據(jù)遷移率太大

遷移前

image

遷移后

image
建議添加節(jié)點時,采用多倍擴容的方式
image

② 一致性哈希分區(qū)方式

基本規(guī)則,順時針的方式式

image

一致性哈希的擴容

擴容前

image

擴容后

image

特點總結(jié)

image

③ 虛擬槽分區(qū)方式(Redis Cluster 使用了此方式)

虛擬槽的分配
image

2.Redis 集群的優(yōu)勢

自動分割數(shù)據(jù)到不同的節(jié)點上。
整個集群的部分節(jié)點失敗或者不可達的情況下能夠繼續(xù)處理命令。

特點

主從復(fù)制

實現(xiàn)了高可用

數(shù)據(jù)分片存儲

集群節(jié)點的 meet 過程

image
image

指派槽

image

客戶端和槽

image

3. Redis 集群的安裝

原生命令安裝

步驟

  1. 配置開啟集群節(jié)點

  2. 配置 meet

  3. 指派槽

  4. 配置主從

實例操作

準備兩臺虛擬機:
一臺啟動三個 Redis 實例作為 主節(jié)點
另一臺啟動三個 Redis 實例作為 從節(jié)點

架構(gòu)圖
image
實驗步驟
  1. 先編輯一個集群的配置文件

編譯配置文件 /etc/redis/cluster-redis-7001.conf, 添加如下內(nèi)容:

bind 0.0.0.0
port 7001
daemonize yes

# 允許任何地址不使用密碼訪問我
protected-mode no
dir "/redis/data/"
logfile  "cluster-7001.log"
dbfilename "cluster-dump-7001.log"
cluster-enabled yes
cluster-config-file nodes-7001.conf

# 不需要集群的全部節(jié)點完好才提供服務(wù)
cluster-require-full-coverage no

  1. 再創(chuàng)建其他集群的配置文件

    image
[root@s1 redis]# sed 's/7001/7002/g' cluster-redis-7001.conf > cluster-redis-7002.conf
[root@s1 redis]# sed 's/7001/7003/g' cluster-redis-7001.conf > cluster-redis-7003.conf
[root@s1 redis]# sed 's/7001/7011/g' cluster-redis-7001.conf > cluster-redis-7011.conf
[root@s1 redis]# sed 's/7001/7012/g' cluster-redis-7001.conf > cluster-redis-7012.conf
[root@s1 redis]# sed 's/7001/7013/g' cluster-redis-7001.conf > cluster-redis-7013.conf

拷貝從節(jié)點的配置文件到另外一臺主機上

需要保證另一臺主機上有目錄 /etc/redis/, 因為這里計劃把所有的配置文件放在此目錄下

[root@s1 redis]# scp -r cluster-redis-701*  root@172.16.153.179:/etc/redis/

  1. 首先,需要啟動主節(jié)點的服務(wù)進程
[root@s1 ~]# redis-server  /etc/redis/cluster-redis-7001.conf
[root@s1 ~]# redis-server  /etc/redis/cluster-redis-7002.conf
[root@s1 ~]# redis-server  /etc/redis/cluster-redis-7003.conf

  1. 之后,再啟動從節(jié)點的服務(wù)進程
image
[root@s2 ~]# mkdir -p /redis/data
[root@s2 ~]# redis-server  /etc/redis/cluster-redis-7011.conf
[root@s2 ~]# redis-server  /etc/redis/cluster-redis-7012.conf
[root@s2 ~]# redis-server  /etc/redis/cluster-redis-7013.conf

檢查進程

ps   -ef  | grep  redis-server

假設(shè)你現(xiàn)在去連接到任意一個節(jié)點上執(zhí)行操作會返回集群目前是沒有啟動的信息。

原因是目前集群各節(jié)點之間沒有進行 meet 操作,都是各自孤立的狀態(tài)。

image

可以使用如下命令查看集群的相關(guān)信息

image

還可以查看某一個集群節(jié)點信息,第一列是集群節(jié)點 ID

image
  1. 集群節(jié)點之間的 meet

我們下面使用主節(jié)點 172.16.153.178:7001 去依次的 meet 其他 5 個節(jié)點。

image

查看集群信息和節(jié)點 信息

image
image
  1. 給集群節(jié)點分配 數(shù)據(jù)槽
    集群的槽號是 從 0 開始,到 16383 結(jié)束,共 16384 個。

槽的分配是拿 16384 除以集群中主節(jié)點的個數(shù),得到每個主節(jié)點應(yīng)該被分配給槽的數(shù)量。

所以現(xiàn)在的計劃是:

image

命令

redis-cli  -h 被添加的主機 IP -p 端口 cluster  addslots  槽號

假如給 7001 分配 0 號槽。命令應(yīng)該是:

redis-cli  -h 172.16.153.178  -p 7001 cluster  addslots  0

每次只能分配一個 槽號,所以我們可以寫個腳本,當然這種方式是不會在生產(chǎn)環(huán)境中使用的,這里只是為了理解集群的架構(gòu)關(guān)系。

腳本

#!/bin/sh

target_host_ip=$1
target_host_port=$2

star=$3
end=$4

for slot in $(seq ${star} ${end})
do
    echo "正在給 ${target_host_ip} ${target_host_port} 添加${slot}"
    redis-cli -h ${target_host_ip} -p ${target_host_port}  cluster addslots ${slot}

done

使用腳本

sh mutil-addslots.sh 172.16.153.178 7002 5462 10922
sh mutil-addslots.sh 172.16.153.178 7003 10923 16383

多線程版

image

最后查看集群信息

image

可以發(fā)現(xiàn)此時集群的狀態(tài)是 OK 的。

查看節(jié)點信息

image
  1. 給集群節(jié)點配置主從關(guān)系

命令語法

redis-cli   -p  從節(jié)點端口   cluster  replicate  主節(jié)點的 ID

實操

切換到從節(jié)點所在的主機,這樣有便于操作

先獲取到集群各個節(jié)點的 ID

image

再按照計劃好的進行復(fù)制關(guān)系的設(shè)置

[root@s2 ~]# redis-cli -p 7011 cluster replicate 587b37f1bbe86dcce2b21e3890a61e9b5cdabade
OK
[root@s2 ~]# redis-cli -p 7012 cluster replicate 9d2617ed1892ad08d0bc66b50dada6d53901cce3
OK
[root@s2 ~]# redis-cli -p 7013 cluster replicate e3f9b763619c0f94ce943e57766001f0283f6c51
OK

查看集群節(jié)點信息,驗證主從關(guān)系

redis-cli   -p  7011 cluster  nodes

image

完全配置好后,可以觀察集群的數(shù)據(jù)槽的分配情況

redis-cli -p 7011 cluster  slots

最后用客戶端登錄集群的方式登錄到集群中的任意一個節(jié)點,設(shè)置鍵值對進行測試。

image

官方工具安裝

官方工具依賴于 Ruby

1. 下載、編譯、安裝 Ruby

點我到下載頁面

[root@s1 ~]# wget https://cache.ruby-lang.org/pub/ruby/2.6/ruby-2.6.1.tar.gz

安裝依賴包

yum  install  zlib-devel readline openssl-devel

點我查看具體安裝方法

$ ./configure
$ make
$ sudo make install

2. 安裝 rubygem redis

一個 ruby 語言實現(xiàn)的訪問 Redis 集群的客戶端

點我到官網(wǎng)下載地址

 wget https://rubygems.org/rubygems/rubygems-3.0.2.tgz
 tar -xf rubygems-3.0.2.tgz
cd rubygems-3.0.2/
ruby setup.rb

gem install redis

3. 安裝 redis-trib.rb

redis-trib 位于 Redis 源碼的 src 文件夾中, 它是一個 Ruby 程序, 這個程序通過向?qū)嵗l(fā)送特殊命令來完成創(chuàng)建新集群, 檢查集群, 或者對集群進行重新分片(reshared)等工作。

cp   ~/redis-4.0.10/src/redis-trib.rb   /url/local/bin/

配置集群

假如你完全安裝這個文檔做的實驗的換,此時配置集群之前,需要把之前的集群進程都停掉。

先在從節(jié)點上執(zhí)行,再到主節(jié)點上執(zhí)行

ps -ef | grep redis-server | grep -v 'grep' | awk '{print $2}' |xargs  kill

接著分別在兩臺主機上,把之前集群產(chǎn)生的數(shù)據(jù)清除

[root@s1 ~]# rm -rf /redis/data/

[root@s2 ~]# rm -rf /redis/data/

再重新啟動這些節(jié)點的服務(wù)進程
先在主節(jié)點上執(zhí)行

image

再在從節(jié)點上執(zhí)行

image

之后使用如下命令創(chuàng)建集群

redis-trib-rb  create  --replicas  1  主節(jié)點1IP:端口    主節(jié)點2P::端口    主節(jié)點3P::端口   從節(jié)點1P::端口    從節(jié)點2P::端口    從節(jié)點3P::端口  

選項–replicas 1 表示我們希望為集群中的每個主節(jié)點創(chuàng)建一個從節(jié)點。

redis-trib.rb create --replicas 1 172.16.153.178:7001 172.16.153.178:7002 172.16.153.178:7003 172.16.153.179:7011 172.16.153.179:7012 172.16.153.179:7013

image
image
image


4. 深入集群

集群的伸縮

添加節(jié)點(擴容)

  1. 準備節(jié)點

    image

2.加入集群中

image
image
  1. 實例操作
image
image
  1. 完成后觀察各主節(jié)點的數(shù)據(jù)槽的分配情況
image

減少節(jié)點(縮容)

image

縮容時的遷移槽

image

忘記節(jié)點操作

image
實驗

命令:

./redis-trib.rb  reshard --from   下線節(jié)點 ID  --to  集群中的任意主節(jié)點 ID  --slots   遷移到槽數(shù)   目前集群中任意節(jié)點 IP:端口

注意:
需要把下線節(jié)點的槽數(shù)平均遷移到剩余的所有節(jié)點,所以需要分配分次執(zhí)行上面的命令。
并且,每次都集群中的主節(jié)點應(yīng)該不同。

刪除節(jié)點

當我們使用 redis-trib.rb 工具時,只需要在目前集群中的任意一個節(jié)點中執(zhí)行如下命令即可。

注意:
你應(yīng)該始終先刪除從節(jié)點,再刪除主節(jié)點

image
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容