Redis 高级(主从,哨兵,集群)

一、主从复制

 
image

Redis 的主从复制特点

 
image

1. 配置主从

实现方式同样有两种: 命令方式和配置文件方式

命令方式

只需要在从服务器上执行如下命令即可

slaveof  主服务器的IP  端口号

slaveof 命令是异步的,不阻塞。
并且此时,从服务器现有的数据会先被清空,之后再同步主服务器的数据。

停止一台从服务器的复制操作,在此台服务器上执行如下命令

slaveof no   one

配置文件的方式如下

只需要在从服务器上配置即可

修改配置文件
假如主服务器 IP 是: 172.16.153.178
端口是: 6379

# slaveof <masterip> <masterport>
slaveof  172.16.153.178 6379

// 配置此服务器只提供读取操作
slave-read-only yes

之后重启从主机的 Redis 服务

查看主从信息

127.0.0.1:6379> info  replication

二、主从 + Sentinel 哨兵模式

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

Redis 的 Sentinel 系统用于管理多个 Redis 服务器(instance), 该系统执行以下三个任务:

  • 监控(Monitoring): Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。

  • 提醒(Notification): 当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。

  • 自动故障迁移(Automatic failover): 当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作, 它会将失效主服务器的其中一个从服务器升级为新的主服务器, 并让失效主服务器的其他从服务器改为复制新的主服务器; 当客户端试图连接失效的主服务器时, 集群也会向客户端返回新主服务器的地址, 使得集群可以使用新主服务器代替失效服务器。

Redis Sentinel 是一个分布式系统, 你可以在一个架构中运行多个 Sentinel 进程(progress), 这些进程使用流言协议(gossip protocols)来接收关于主服务器是否下线的信息, 并使用投票协议(agreement protocols)来决定是否执行自动故障迁移, 以及选择哪个从服务器作为新的主服务器。

虽然 Redis Sentinel 释出为一个单独的可执行文件 redis-sentinel , 但实际上它只是一个运行在特殊模式下的 Redis 服务器。

此种模式下,客户端要访问的 服务 IP 不是主节点,而是 sentiner 服务器的 IP。

架构图

 
image

Redis Sentinel 故障转移

 
image

架构的扩展应用

 
image

1. 配置主从

a. 快速生成主节点的配置文件

编译全新文件 /etc/redis/redis-6380.conf, 添加如下内容

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

假如是多个主机实现的,就需要更改为 protected-mode yes
并且添加 bind 0.0.0.0

b. 快速生成从节点的配置文件

[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

查看配置文件内容,检验配置结果

[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. 配置主从关系

[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. 启动服务,并验证进程

[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 ~]#

假如日志中出现如下警告信息

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: 临时设置生效:
shell> sysctl -w net.core.somaxconn=1024

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

然后执行命令
sysctl -p

WARNING overcommit_memory ...
方法1: 临时设置生效:
shell> sysctl -w vm.overcommit_memory=1

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

然后执行命令
sysctl -p

e. 查看主从复制信息

 
image

2. 配置 sentinel

获取程序

Sentinel 程序可以在编译后的 src 文档中发现, 它是一个命名为 redis-sentinel 的程序。

运行一个 Sentinel 所需的最少配置如下所示:

Redis 源码中包含了一个名为 sentinel.conf 的文件, 这个文件是一个带有详细注释的 Sentinel 配置文件示例。

运行一个 Sentinel 所需的最少配置如下所示:

// 监控一个 Redis 服务器
// 名称为 mymaster ,IP 为 127.0.0.1 端口为 6379
// 最后的 2  是指最少有 2 给 Sentinel 实例同意一台 redis 服务器宕机,才会认为 客观下线。
// sentinel monitor  自定义的主节点名称 主节点的 IP  主节点端口   票数 

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 认为服务器已经断线所需的毫秒数。
如果服务器在给定的毫秒数之内, 没有返回 Sentinel 发送的 PING 命令的回复, 或者返回一个错误, 那么 Sentinel 将这个服务器标记为主观下线(subjectively down,简称 SDOWN )。

不过只有一个 Sentinel 将服务器标记为主观下线并不一定会引起服务器的自动故障迁移: 只有在足够数量的 Sentinel 都将一个服务器标记为主观下线之后, 服务器才会被标记为客观下线(objectively down, 简称 ODOWN ), 这时自动故障迁移才会执行。

将服务器标记为客观下线所需的 Sentinel 数量由对主服务器的配置决定。

parallel-syncs 选项指定了在执行故障转移时, 最多可以有多少个从服务器同时对新的主服务器进行同步, 这个数字越小, 完成故障转移所需的时间就越长。

哨兵的领导者选举

票数和领导者选举有关系

领导者选举的事件发生,必须满足下面的条件

max(票数, (哨兵的个数 / 2) + 1 ) 个哨兵参加选举

才可以选举出领导者,从而完成故障转移。

比如有 5 个哨兵, 配置的票数是 4

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

max(4, 3.5)
4 最大
结果就是需要 4 个哨兵参与选举才可以。

a. 获取并修改配置文件

快速创建三个 sentinel 配置文件
进入到 Redis 源码的目录下,执行如下命令

 
image

修改监听端口

 
image

之后在每个 sentinel 配置文件中添加守护进程方式运行,
并修改dir 配置项的目录,

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

最后别忘了修改监控的主服务器的 IP 和端口正确的 6380

最终其中一个的配置文件应该是这样的

 
image

b. 启动服务并验证

启动服务的语法:

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 所有节点的 IP和一个 Master Name。

第一步从所有的 Sentinel 列表中得到一个有效的 Sentinel 节点。

 
image

第二步向得到的 Sentinel 节点发送查询一个已知的 Master Name 的信息到请求,并得到 Master 节点的信息

 
image

第三步向 Master 节点验证 Maset 角色的真实性

 
image

第四步 客户端 和 Sentiel 之间建立发布订阅关系。

客户端订阅 Sentinel 的频道,一旦 Master 的 IP 信息有变化,客户端就会通过此频道发布的信息得知。

 
image

4. 故障演练

停止 Master 节点的服务

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

不断的刷新其中一个 Sentinel 节点的信息,观察最后一行信息的变化

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



三、 集群

1. 数据分区介绍

 
image

a. 数据分区的方式

 
image

两者的对比

 
image

b. 哈希分区的三种方式

  • 节点取余

  • 一致性哈希

  • 虚拟槽哈希

① 节点取余(不推荐使用)

 
image
问题: 当向集群重添加一个节点时,数据迁移率太大

迁移前

 
image

迁移后

 
image
建议添加节点时,采用多倍扩容的方式
 
image

② 一致性哈希分区方式

基本规则,顺时针的方式式

 
image

一致性哈希的扩容

扩容前

 
image

扩容后

 
image

特点总结

 
image

③ 虚拟槽分区方式(Redis Cluster 使用了此方式)

虚拟槽的分配
 
image

2.Redis 集群的优势

自动分割数据到不同的节点上。
整个集群的部分节点失败或者不可达的情况下能够继续处理命令。

特点

主从复制

实现了高可用

数据分片存储

集群节点的 meet 过程

 
image
 
image

指派槽

 
image

客户端和槽

 
image

3. Redis 集群的安装

原生命令安装

步骤

  1. 配置开启集群节点

  2. 配置 meet

  3. 指派槽

  4. 配置主从

实例操作

准备两台虚拟机:
一台启动三个 Redis 实例作为 主节点
另一台启动三个 Redis 实例作为 从节点

架构图
 
image
实验步骤
  1. 先编辑一个集群的配置文件

编译配置文件 /etc/redis/cluster-redis-7001.conf, 添加如下内容:

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

# 不需要集群的全部节点完好才提供服务
cluster-require-full-coverage no

  1. 再创建其他集群的配置文件

     
    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

拷贝从节点的配置文件到另外一台主机上

需要保证另一台主机上有目录 /etc/redis/, 因为这里计划把所有的配置文件放在此目录下

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

  1. 首先,需要启动主节点的服务进程
[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. 之后,再启动从节点的服务进程
 
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

假设你现在去连接到任意一个节点上执行操作会返回集群目前是没有启动的信息。

原因是目前集群各节点之间没有进行 meet 操作,都是各自孤立的状态。

 
image

可以使用如下命令查看集群的相关信息

 
image

还可以查看某一个集群节点信息,第一列是集群节点 ID

 
image
  1. 集群节点之间的 meet

我们下面使用主节点 172.16.153.178:7001 去依次的 meet 其他 5 个节点。

 
image

查看集群信息和节点 信息

 
image
 
image
  1. 给集群节点分配 数据槽
    集群的槽号是 从 0 开始,到 16383 结束,共 16384 个。

槽的分配是拿 16384 除以集群中主节点的个数,得到每个主节点应该被分配给槽的数量。

所以现在的计划是:

 
image

命令

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

假如给 7001 分配 0 号槽。命令应该是:

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

每次只能分配一个 槽号,所以我们可以写个脚本,当然这种方式是不会在生产环境中使用的,这里只是为了理解集群的架构关系。

脚本

#!/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

可以发现此时集群的状态是 OK 的。

查看节点信息

 
image
  1. 给集群节点配置主从关系

命令语法

redis-cli   -p  从节点端口   cluster  replicate  主节点的 ID

实操

切换到从节点所在的主机,这样有便于操作

先获取到集群各个节点的 ID

 
image

再按照计划好的进行复制关系的设置

[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

查看集群节点信息,验证主从关系

redis-cli   -p  7011 cluster  nodes

 
image

完全配置好后,可以观察集群的数据槽的分配情况

redis-cli -p 7011 cluster  slots

最后用客户端登录集群的方式登录到集群中的任意一个节点,设置键值对进行测试。

 
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 语言实现的访问 Redis 集群的客户端

点我到官网下载地址

 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 程序, 这个程序通过向实例发送特殊命令来完成创建新集群, 检查集群, 或者对集群进行重新分片(reshared)等工作。

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

配置集群

假如你完全安装这个文档做的实验的换,此时配置集群之前,需要把之前的集群进程都停掉。

先在从节点上执行,再到主节点上执行

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

接着分别在两台主机上,把之前集群产生的数据清除

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

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

再重新启动这些节点的服务进程
先在主节点上执行

 
image

再在从节点上执行

 
image

之后使用如下命令创建集群

redis-trib-rb  create  --replicas  1  主节点1IP:端口    主节点2P::端口    主节点3P::端口   从节点1P::端口    从节点2P::端口    从节点3P::端口  

选项–replicas 1 表示我们希望为集群中的每个主节点创建一个从节点。

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. 深入集群

集群的伸缩

添加节点(扩容)

  1. 准备节点

     
    image

2.加入集群中

 
image
 
image
  1. 实例操作
 
image
 
image
  1. 完成后观察各主节点的数据槽的分配情况
 
image

减少节点(缩容)

 
image

缩容时的迁移槽

 
image

忘记节点操作

 
image
实验

命令:

./redis-trib.rb  reshard --from   下线节点 ID  --to  集群中的任意主节点 ID  --slots   迁移到槽数   目前集群中任意节点 IP:端口

注意:
需要把下线节点的槽数平均迁移到剩余的所有节点,所以需要分配分次执行上面的命令。
并且,每次都集群中的主节点应该不同。

删除节点

当我们使用 redis-trib.rb 工具时,只需要在目前集群中的任意一个节点中执行如下命令即可。

注意:
你应该始终先删除从节点,再删除主节点

 
image
posted @ 2021-12-28 21:11  CharyGao  阅读(32)  评论(0编辑  收藏  举报