Redis持久化、集群

单点redis存在的问题及解决方案

Redis持久化、集群_第1张图片

1. Redis持久化

1.1 Redis持久化简介

​ Redis数据持久化是指将Redis内存中的数据保存到磁盘上的过程,以防止数据丢失。Redis提供了两种数据持久化的方式,分别是RDB和AOF。

1.2 RDB

1.2.1 RDB简介

​ RDB (Redis DataBase Backup file) redis数据库备份文件 也叫Redis数据快照,RDB持久化是通过定时手动触发快照命令,将内存中的数据集以二进制格式保存到磁盘上的一种方式。

优点:文件体积小(可以设置是否压缩,一般不压缩),恢复速度快,适合备份和传输

缺点:

​ 1.RDB执行时间间隔长,两次RDB之间写入数据会有丢失数据的风险

​ 2.在执行快照时会占用CPU和内存资源,fork子进程、压缩、写入RDB都比较耗时 ,可能影响服务性能。

1.2.2 RDB执行的时机:

  • 手动触发:通过执行save(一般不用)bgsave命令,可以立即或后台生成RDB文件。save命令会阻塞Redis的服务,直到RDB文件生成完毕;bgsave命令会创建一个子进程来生成RDB文件,不影响Redis的服务。
  • 自动触发:通过配置redis.conf文件中的save参数,可以设置一定的时间和修改次数的条件,当满足条件时,会自动触发bgsave命令。例如,save 900 1表示900秒内至少有一次修改则触发保存操作。
  • 关闭触发:当正常关闭Redis时,如果没有开启AOF持久化,会自动触发save命令,将最新的数据保存到RDB文件中。如果意外宕机,不会触发RDB持久化,可能会丢失最后一次持久化后的数据。
  • 清空触发:当执行flushall命令时,会自动触发bgsave命令,将空的数据集保存到RDB文件中,覆盖原有的RDB文件。

save(一般不用):

127.0.0.1:6379> save

​ save命令会直接调用rdbSave函数,阻塞Redis主进程,直到保存完成为止。在主进程阻塞期间,服务器不能处理客户端的任何请求

bgsave:

127.0.0.1:6379> bgsave

bgsave命令会fork出一个子进程,子进程负责调用rdbSave函数,并在保存完成之后向主进程发送信号,通知保存已完成。Redis服务器在bgsave执行期间仍然可以继续处理客户端的请求。

**注意:**由于save会阻塞主进程,此时服务器不能处理客户端的任何请求,bgsave会fork出一个子进程不会对主进程造成影响,因此一般使用bgsave来执行RDB

(save和bgsave的区别主要在于是否影响Redis的服务性能。save命令会导致Redis暂停服务,可能造成客户端的超时或失败。bgsave命令不会影响Redis的服务,但是会增加Redis的内存占用,因为需要复制数据集给子进程。)

1.2.3 RDB执行原理

RDB执行原理:

​ bgsave命令一开始 就会 fork 主进程得到子进程 ,子进程会共享主进程的内存数据. 完成fork之后读取内存中的数据并写入RDB文件。

fork采用的是 写时复制(copy-on-write) 技术,当主进程执行读操作的时候,访问共享内存 ,当主进程执行写的操作,则会拷贝一份数据,执行写操作

RDB执行流程:

Redis持久化、集群_第2张图片

1.2.4 RDB的相关配置

进入redis-6.2.4目录,打开redis.conf文件

  • RDB文件是否压缩:

    Redis持久化、集群_第3张图片

  • RDB文件名

    Redis持久化、集群_第4张图片

  • RDB文件保存目录

    Redis持久化、集群_第5张图片

  • 设置Redis的RDB持久化的策略

    Redis持久化、集群_第6张图片

1.3 AOF

1.3.1 AOF简介

AOFAppend Only File的缩写,是Redis的一种持久化方式,它可以将每个写命令以文本格式追加到日志文件中,实现增量持久化。AOF的主要作用是解决了数据持久化的实时性。目前已经是Redis持久化的主流方式。

优点:

  • **可以保证数据不丢失:**根据配置的同步策略,最多丢失一秒内的数据。
  • **文件内容易读:**便于修复和处理。
  • **可以自动启用重写机制:**压缩和瘦身相关的AOF文件。

缺点:

  • **文件体积大:**可能有冗余数据。
  • **恢复速度慢:**需要重新执行所有的写命令。
  • **可能影响磁盘IO性能:**需要不断地将写命令写入和同步到磁盘上。

1.3.2 AOF配置

在redis.conf文件中进行配置:

  • AOF的开启(默认为关闭状态):
    Redis持久化、集群_第7张图片

  • AOF文件名

    Redis持久化、集群_第8张图片

  • AOF执行策略:

    执行策略 描述
    appendfsync always 表每执行一次写命令,立刻记录到AOF文件。 性能最低,可靠性最好
    appendfsync everysec 写命令执行完毕之后先放入AOF的缓冲区,然后每间隔1秒将缓冲区的内容写入AOF文件中,这个是默认的。 性能,可靠性都可以
    appendfsync no 由操作系统决定什么时间写入到我们的磁盘中。 性能最好,可靠性最差

    Redis持久化、集群_第9张图片

  • Redis何时自动触发AOF文件的重写

    Redis持久化、集群_第10张图片

1.3.3 AOF的持久化

1.开启AOF(默认为关闭)

appendonly no->appendonly yes

2.关闭RDB

#将注释取消掉,禁用RDB
#save ”“
->
save ""

3.启动Redis,连接Redis客户端

redis-server redis.conf
redis-cli -p 6379

4.进行数据读写,查看aof文件存储写操作情况

Redis持久化、集群_第11张图片

总结:RDB和AOF的对比

RDB AOF
使用场景 容忍分钟数据的丢失,追求更快的启动速度,例如缓存系统 对数据安全性要求较高,不允许有任何数据丢失的场景,例如金融系统。
持久化方式 定时对整个内存做快照 记录每一次执行的命令,以保证数据的完整性。
数据完整性 不完整,两次之间会丢失数据 相对完整 刷盘策略
文件大小 有压缩,是二进制格式的快照,文件体积小 记录每条命令,体积大
宕机恢复速度 较快,因为只需加载最近的数据快照即可,数据完整性不如AOF 较慢,因为需要逐一重放写操作以还原数据状态,数据完整性高
数据恢复优先级
资源占用 高,在保存快照时可能会占用较多内存。 低,但由于需要不断追加写操作,可能会占用较多磁盘空间。

2. Redis集群

Redis 集群是 Redis 数据库的一种分布式部署方式,它通过将数据分散存储在多个节点上来提供高可用性和可扩展性。Redis 集群通常由多个主节点和若干个从节点组成,每个节点都可以存储部分数据。下面是 Redis 集群的一些关键特点:

  1. 数据分片:Redis 集群将数据划分为多个槽(slot),默认共有 16384 个槽,每个槽可以存储一个键值对。这些槽均匀地分布在集群各个节点上,每个节点负责管理一部分槽。
  2. 主从复制:每个主节点可以有多个从节点。主节点负责响应写操作和部分读操作,而从节点则负责复制主节点的数据,并能够处理读操作。主从复制实现了数据的冗余备份和高可用性。
  3. 节点间通信:Redis 集群使用 gossip 协议进行节点间的通信和信息交换。每个节点都会定期与其他节点交换集群拓扑信息,以保持整个集群的状态一致性。
  4. 客户端路由:客户端通过集群客户端连接到 Redis 集群,集群客户端负责将不同的键值对请求路由到相应的节点上,实现对数据的读写操作。

使用 Redis 集群可以提供更高的可用性、容错性和扩展性,同时还能够分散负载和提高读写性能。在配置和管理 Redis 集群时,你需要考虑节点的部署、数据迁移、故障恢复等方面的问题。

2.1 单机安装Redis

首先需要安装Redis所需要的依赖:

yum install -y gcc tcl

然后将Redis安装包上传到虚拟机的任意目录:

Redis持久化、集群_第12张图片

例如,我放到了/tmp目录:

Redis持久化、集群_第13张图片

解压缩:

tar -xvf redis-6.2.4.tar.gz

解压后:

Redis持久化、集群_第14张图片

进入redis目录:

cd redis-6.2.4

运行编译命令:

make && make install

如果没有出错,应该就安装成功了。

然后修改redis.conf文件中的一些配置:

# 绑定地址,默认是127.0.0.1,会导致只能在本地访问。修改为0.0.0.0则可以在任意IP访问
bind 0.0.0.0
# 数据库数量,设置为1
databases 1

启动Redis:

redis-server redis.conf

停止redis服务:

redis-cli shutdown

2.2 Redis主从集群

2.2.1 集群结构

搭建的主从集群结构如图:

Redis持久化、集群_第15张图片

共包含三个节点,一个主节点,两个从节点。

这里我们会在同一台虚拟机中开启3个redis实例,模拟主从集群,信息如下:

IP PORT 角色
192.168.150.101 7001 master
192.168.150.101 7002 slave
192.168.150.101 7003 slave

2.2.2 准备实例和配置

要在同一台虚拟机开启3个实例,必须准备三份不同的配置文件和目录,配置文件所在目录也就是工作目录。

1)创建目录

我们创建三个文件夹,名字分别叫7001、7002、7003:

# 进入/tmp目录
cd /tmp
# 创建目录
mkdir 7001 7002 7003

如图:

Redis持久化、集群_第16张图片

2)恢复原始配置

修改redis-6.2.4/redis.conf文件,将其中的持久化模式改为默认的RDB模式,AOF保持关闭状态。

# 开启RDB
# save ""
save 3600 1
save 300 100
save 60 10000

# 关闭AOF
appendonly no

3)拷贝配置文件到每个实例目录

然后将redis-6.2.4/redis.conf文件拷贝到三个目录中(在/tmp目录执行下列命令):

# 方式一:逐个拷贝
cp redis-6.2.4/redis.conf 7001
cp redis-6.2.4/redis.conf 7002
cp redis-6.2.4/redis.conf 7003
# 方式二:管道组合命令,一键拷贝
echo 7001 7002 7003 | xargs -t -n 1 cp redis-6.2.4/redis.conf

4)修改每个实例的端口、工作目录

修改每个文件夹内的配置文件,将端口分别修改为7001、7002、7003,将rdb文件保存位置都修改为自己所在目录(在/tmp目录执行下列命令):

sed -i -e 's/6379/7001/g' -e 's/dir .\//dir \/tmp\/7001\//g' 7001/redis.conf
sed -i -e 's/6379/7002/g' -e 's/dir .\//dir \/tmp\/7002\//g' 7002/redis.conf
sed -i -e 's/6379/7003/g' -e 's/dir .\//dir \/tmp\/7003\//g' 7003/redis.conf

5)修改每个实例的声明IP

虚拟机本身有多个IP,为了避免将来混乱,我们需要在redis.conf文件中指定每一个实例的绑定ip信息,格式如下:

# redis实例的声明 IP
replica-announce-ip 192.168.150.101

每个目录都要改,我们一键完成修改(在/tmp目录执行下列命令):

# 逐一执行
sed -i '1a replica-announce-ip 192.168.150.101' 7001/redis.conf
sed -i '1a replica-announce-ip 192.168.150.101' 7002/redis.conf
sed -i '1a replica-announce-ip 192.168.150.101' 7003/redis.conf

# 或者一键修改
printf '%s\n' 7001 7002 7003 | xargs -I{} -t sed -i '1a replica-announce-ip 192.168.150.101' {}/redis.conf

2.2.3 启动

为了方便查看日志,我们打开3个ssh窗口,分别启动3个redis实例,启动命令:

# 第1个
redis-server 7001/redis.conf
# 第2个
redis-server 7002/redis.conf
# 第3个
redis-server 7003/redis.conf

启动后:

Redis持久化、集群_第17张图片

如果要一键停止,可以运行下面命令:

printf '%s\n' 7001 7002 7003 | xargs -I{} -t redis-cli -p {} shutdown

2.2.4 开启主从关系

现在三个实例还没有任何关系,要配置主从可以使用replicaof 或者slaveof(5.0以前)命令。

有临时和永久两种模式:

  • 修改配置文件(永久生效)

    • 在redis.conf中添加一行配置:
  • 使用redis-cli客户端连接到redis服务,执行slaveof命令(重启后失效):

    slaveof <masterip> <masterport>
    

注意:在5.0以后新增命令replicaof,与salveof效果一致。

这里我们为了演示方便,使用方式二。

通过redis-cli命令连接7002,执行下面命令:

# 连接 7002
redis-cli -p 7002
# 执行slaveof
slaveof 192.168.150.101 7001

通过redis-cli命令连接7003,执行下面命令:

# 连接 7003
redis-cli -p 7003
# 执行slaveof
slaveof 192.168.150.101 7001

然后连接 7001节点,查看集群状态:

# 连接 7001
redis-cli -p 7001
# 查看状态
info replication

结果:

Redis持久化、集群_第18张图片

2.2.5 测试

执行下列操作以测试:

  • 利用redis-cli连接7001,执行set num 123

  • 利用redis-cli连接7002,执行get num,再执行set num 666

  • 利用redis-cli连接7003,执行get num,再执行set num 888

可以发现,只有在7001这个master节点上可以执行写操作,7002和7003这两个slave节点只能执行读操作

=============================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================

2.2.6 实操记录

redis/redis.conf配置文件:

  1. 75行-

    注释掉bind 127.0.0.1 -::1 配置bind 0.0.0.0

  2. 382行-

    取消注释

    save 3600 1
    save 300 100
    save 60 10000

  3. 1254行-

    appendonly no

  4. 328行-数据库

    databases 1

配置主从 一主二从

[root@xwk ~]# cd /tmp
[root@xwk tmp]# ls
hsperfdata_root   mysql.sock       redis-6.2.4
ks-script-aYmaht  mysql.sock.lock  yum.log
[root@xwk tmp]# mkdir 7001 7002 7003
[root@xwk tmp]# ll
total 12
drwxr-xr-x. 2 root  root     6 Nov 11 23:03 7001
drwxr-xr-x. 2 root  root     6 Nov 11 23:03 7002
drwxr-xr-x. 2 root  root     6 Nov 11 23:03 7003
drwxr-xr-x. 2 root  root    18 Nov 11 17:44 hsperfdata_root
-rwx------. 1 root  root   836 Nov 11 17:13 ks-script-aYmaht
srwxrwxrwx. 1 mysql mysql    0 Nov 11 18:07 mysql.sock
-rw-------. 1 mysql mysql    5 Nov 11 18:07 mysql.sock.lock
drwxrwxr-x. 7 root  root  4096 Jun  1  2021 redis-6.2.4
-rw-------. 1 root  root     0 Nov 11 17:09 yum.log
[root@xwk tmp]# cd redis-6.2.4/
[root@xwk redis-6.2.4]# ll
total 236
-rw-rw-r--.  1 root root 28118 Jun  1  2021 00-RELEASENOTES
-rw-rw-r--.  1 root root    51 Jun  1  2021 BUGS
-rw-rw-r--.  1 root root  5026 Jun  1  2021 CONDUCT
-rw-rw-r--.  1 root root  3384 Jun  1  2021 CONTRIBUTING
-rw-rw-r--.  1 root root  1487 Jun  1  2021 COPYING
drwxrwxr-x.  7 root root   213 Nov 11 18:27 deps
-rw-rw-r--.  1 root root    11 Jun  1  2021 INSTALL
-rw-rw-r--.  1 root root   151 Jun  1  2021 Makefile
-rw-rw-r--.  1 root root  6888 Jun  1  2021 MANIFESTO
-rw-rw-r--.  1 root root 21567 Jun  1  2021 README.md
-rw-rw-r--.  1 root root 93724 Jun  1  2021 redis.conf
-rwxrwxr-x.  1 root root   275 Jun  1  2021 runtest
-rwxrwxr-x.  1 root root   279 Jun  1  2021 runtest-cluster
-rwxrwxr-x.  1 root root  1046 Jun  1  2021 runtest-moduleapi
-rwxrwxr-x.  1 root root   281 Jun  1  2021 runtest-sentinel
-rw-rw-r--.  1 root root 13768 Jun  1  2021 sentinel.conf
drwxrwxr-x.  3 root root 12288 Nov 11 18:28 src
drwxrwxr-x. 11 root root   182 Jun  1  2021 tests
-rw-rw-r--.  1 root root  3055 Jun  1  2021 TLS.md
drwxrwxr-x.  9 root root  4096 Jun  1  2021 utils
[root@xwk redis-6.2.4]# vim redis.conf
[root@xwk redis-6.2.4]# cd ..
[root@xwk tmp]# cp redis-6.2.4/redis.conf 7001
[root@xwk tmp]# cp redis-6.2.4/redis.conf 7002
[root@xwk tmp]# cp redis-6.2.4/redis.conf 7003
[root@xwk tmp]# sed -i -e 's/6379/7001/g' -e 's/dir .\//dir \/tmp\/7001
[root@xwk tmp]# sed -i -e 's/6379/7002/g' -e 's/dir .\//dir \/tmp\/7002
[root@xwk tmp]# sed -i -e 's/6379/7003/g' -e 's/dir .\//dir \/tmp\/7003
[root@xwk tmp]# sed -i '1a replica-announce-ip 192.168.145.130' 7001/re
[root@xwk tmp]#    sed -i '1a replica-announce-ip 192.168.145.130' 7002
[root@xwk tmp]#    sed -i '1a replica-announce-ip 192.168.145.130' 7003
[root@xwk tmp]# redis-cli -p 7002
127.0.0.1:7002> slaveof 192.168.145.130 7001
OK
127.0.0.1:7002>
[root@xwk tmp]# redis-cli -p 7003
127.0.0.1:7003> slaveof 192.168.145.130 7001
OK
127.0.0.1:7003>
[root@xwk tmp]# redis-cli -p 7001
127.0.0.1:7001> info replication  #得到奴隶的信息
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.145.130,port=7002,state=online,offset=210,lag=1
slave1:ip=192.168.145.130,port=7003,state=online,offset=210,lag=1
master_failover_state:no-failover
master_replid:61a7de3ef4bd695040410d86be01a4542ae08cad
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:210
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:210
127.0.0.1:7001> set num 123
OK
127.0.0.1:7001>
[root@xwk tmp]# redis-cli -p 7002
127.0.0.1:7002> get num
"123"
127.0.0.1:7002>
[root@xwk tmp]# redis-cli -p 7003
127.0.0.1:7003> get num
"123"
127.0.0.1:7003>

7001

Redis持久化、集群_第19张图片

slaveof 192.168.145.130 7001告知7002与7003从属于7001之后显示最下面的success:

Redis持久化、集群_第20张图片

2.3 Redis哨兵Sentinel

Redis持久化、集群_第21张图片

==

Redis持久化、集群_第22张图片

==

Redis持久化、集群_第23张图片

==

Redis持久化、集群_第24张图片

==

2.3.1 集群结构

这里我们搭建一个三节点形成的Sentinel集群,来监管之前的Redis主从集群。如图:

Redis持久化、集群_第25张图片

三个sentinel实例信息如下:

节点 IP PORT
s1 192.168.150.101 27001
s2 192.168.150.101 27002
s3 192.168.150.101 27003

2.3.2 准备实例和配置

要在同一台虚拟机开启3个实例,必须准备三份不同的配置文件和目录,配置文件所在目录也就是工作目录。

我们创建三个文件夹,名字分别叫s1、s2、s3:

# 进入/tmp目录
cd /tmp
# 创建目录
mkdir s1 s2 s3

如图:

Redis持久化、集群_第26张图片

然后我们在s1目录创建一个sentinel.conf文件,添加下面的内容:

port 27001
sentinel announce-ip 192.168.150.101
sentinel monitor mymaster 192.168.150.101 7001 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
dir "/tmp/s1"

解读:

  • port 27001:是当前sentinel实例的端口
  • sentinel monitor mymaster 192.168.150.101 7001 2:指定主节点信息
    • mymaster:主节点名称,自定义,任意写
    • 192.168.150.101 7001:主节点的ip和端口
    • 2:选举master时的quorum值

然后将s1/sentinel.conf文件拷贝到s2、s3两个目录中(在/tmp目录执行下列命令):

# 方式一:逐个拷贝
cp s1/sentinel.conf s2
cp s1/sentinel.conf s3
# 方式二:管道组合命令,一键拷贝
echo s2 s3 | xargs -t -n 1 cp s1/sentinel.conf

修改s2、s3两个文件夹内的配置文件,将端口分别修改为27002、27003:

sed -i -e 's/27001/27002/g' -e 's/s1/s2/g' s2/sentinel.conf
sed -i -e 's/27001/27003/g' -e 's/s1/s3/g' s3/sentinel.conf

2.3.3 启动

为了方便查看日志,我们打开3个ssh窗口,分别启动3个redis实例,启动命令:

# 第1个
redis-sentinel s1/sentinel.conf
# 第2个
redis-sentinel s2/sentinel.conf
# 第3个
redis-sentinel s3/sentinel.conf

启动后:

Redis持久化、集群_第27张图片

2.3.4 测试

尝试让master节点7001宕机,查看sentinel日志:

Redis持久化、集群_第28张图片

查看7003的日志:

Redis持久化、集群_第29张图片

查看7002的日志:

Redis持久化、集群_第30张图片

实操记录

[root@xwk tmp]# mkdir s1 s2 s3
[root@xwk tmp]# ls
7001  7003             ks-script-aYmaht  mysql.sock.lock  s1  s3
7002  hsperfdata_root  mysql.sock        redis-6.2.4      s2  yum.log
[root@xwk tmp]# cd s1
[root@xwk s1]# vi sentinel.conf
port 27001
sentinel announce-ip 192.168.145.130
sentinel monitor mymaster 192.168.145.130 7001 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
dir "/tmp/s1"
[root@xwk s1]# cd ..
[root@xwk tmp]# cp s1/sentinel.conf s2
[root@xwk tmp]# cp s1/sentinel.conf s3
[root@xwk tmp]# sed -i -e 's/27001/27002/g' -e 's/s1/s2/g' s2/sentinel.conf
[root@xwk tmp]# sed -i -e 's/27001/27003/g' -e 's/s1/s3/g' s3/sentinel.conf
#另开启三个窗口,分别开三个redis,再进行连接
[root@xwk tmp]# redis-cli -p 7002
127.0.0.1:7002> slaveof 192.168.145.130 7001
OK
127.0.0.1:7002>
[root@xwk tmp]# redis-cli -p 7003
127.0.0.1:7003> slaveof 192.168.145.130 7001
OK
127.0.0.1:7003>
[root@xwk tmp]# redis-cli -p 7001
127.0.0.1:7001> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.145.130,port=7002,state=online,offset=4279,lag=0
slave1:ip=192.168.145.130,port=7003,state=online,offset=4424,lag=0
master_failover_state:no-failover
master_replid:bc10942ac67ef4afa4f6169eb6d073719000278b
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:4424
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:4424
127.0.0.1:7001>
#此处退出连接7001
#然后把7001redis服务关闭 哨兵推选7002为master(推选截图在下面:),7001redis服务再次启动,变为slave
#连接7002 查看奴隶
[root@xwk tmp]# redis-cli -p 7002
127.0.0.1:7002> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.145.130,port=7003,state=online,offset=103555,lag=0
slave1:ip=192.168.145.130,port=7001,state=online,offset=103555,lag=0
master_failover_state:no-failover
master_replid:37b6176eda88c113e136fb461f9f19b611b78d1c
master_replid2:bc10942ac67ef4afa4f6169eb6d073719000278b
master_repl_offset:103845
second_repl_offset:12746
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:103845
127.0.0.1:7002>
[root@xwk tmp]#

推选:

Redis持久化、集群_第31张图片

Redis持久化、集群_第32张图片

注意

要开启相应redis服务再进行连接,否则报错

image-20231116203500406

2.4 Redis分片集群

搭建一主一从,三主三从

解决海量数据存储到Redis问题和高并发读写和高可用的问题

Redis持久化、集群_第33张图片

三个主之间互相监测,互相实现了哨兵的功能,一个主挂掉之后,推举其从节点中其中一个为主,继续完成相互监测的功能,如果原主重启会变为从

主7001挂掉之后,数据访问会自动路由到正确的节点:如果在7001挂掉之后,去访问原来存储在7001上的数据,会自动路由到7001原来的从节点8001上(此时从节点8001已经变成主节点,从节点8001有7001原有的数据(主从之间数据同步))读取数据

===

2.4.1 集群结构

分片集群需要的节点数量较多,这里我们搭建一个最小的分片集群,包含3个master节点,每个master包含一个slave节点,结构如下:

Redis持久化、集群_第34张图片

这里我们会在同一台虚拟机中开启6个redis实例,模拟分片集群,信息如下:

IP PORT 角色
192.168.150.101 7001 master
192.168.150.101 7002 master
192.168.150.101 7003 master
192.168.150.101 8001 slave
192.168.150.101 8002 slave
192.168.150.101 8003 slave

2.4.2 准备实例和配置

删除之前的7001、7002、7003这几个目录,重新创建出7001、7002、7003、8001、8002、8003目录:

# 进入/tmp目录
cd /tmp
# 删除旧的,避免配置干扰
rm -rf 7001 7002 7003
# 创建目录
mkdir 7001 7002 7003 8001 8002 8003

在/tmp下准备一个新的redis.conf文件,内容如下:

port 6379
# 开启集群功能
cluster-enabled yes
# 集群的配置文件名称,不需要我们创建,由redis自己维护
cluster-config-file /tmp/6379/nodes.conf
# 节点心跳失败的超时时间
cluster-node-timeout 5000
# 持久化文件存放目录
dir /tmp/6379
# 绑定地址
bind 0.0.0.0
# 让redis后台运行
daemonize yes
# 注册的实例ip
replica-announce-ip 192.168.150.101
# 保护模式
protected-mode no
# 数据库数量
databases 1
# 日志
logfile /tmp/6379/run.log

将这个文件拷贝到每个目录下:

# 进入/tmp目录
cd /tmp
# 执行拷贝
echo 7001 7002 7003 8001 8002 8003 | xargs -t -n 1 cp redis.conf

修改每个目录下的redis.conf,将其中的6379修改为与所在目录一致:

# 进入/tmp目录
cd /tmp
# 修改配置文件
printf '%s\n' 7001 7002 7003 8001 8002 8003 | xargs -I{} -t sed -i 's/6379/{}/g' {}/redis.conf

2.4.3 启动

因为已经配置了后台启动模式,所以可以直接启动服务:

# 进入/tmp目录
cd /tmp
# 一键启动所有服务
printf '%s\n' 7001 7002 7003 8001 8002 8003 | xargs -I{} -t redis-server {}/redis.conf

通过ps查看状态:

ps -ef | grep redis

发现服务都已经正常启动:

Redis持久化、集群_第35张图片

如果要关闭所有进程,可以执行命令:

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

或者(推荐这种方式):

printf '%s\n' 7001 7002 7003 8001 8002 8003 | xargs -I{} -t redis-cli -p {} shutdown

2.4.4 创建集群

虽然服务启动了,但是目前每个服务之间都是独立的,没有任何关联。

我们需要执行命令来创建集群,在Redis5.0之前创建集群比较麻烦,5.0之后集群管理命令都集成到了redis-cli中。

1)Redis5.0之前

Redis5.0之前集群命令都是用redis安装包下的src/redis-trib.rb来实现的。因为redis-trib.rb是有ruby语言编写的所以需要安装ruby环境。

# 安装依赖
yum -y install zlib ruby rubygems
gem install redis

然后通过命令来管理集群:

# 进入redis的src目录
cd /tmp/redis-6.2.4/src
# 创建集群
./redis-trib.rb create --replicas 1 192.168.150.101:7001 192.168.150.101:7002 192.168.150.101:7003 192.168.150.101:8001 192.168.150.101:8002 192.168.150.101:8003

2)Redis5.0以后

我们使用的是Redis6.2.4版本,集群管理以及集成到了redis-cli中,格式如下:

redis-cli --cluster create --cluster-replicas 1 192.168.150.101:7001 192.168.150.101:7002 192.168.150.101:7003 192.168.150.101:8001 192.168.150.101:8002 192.168.150.101:8003

命令说明:

  • redis-cli --cluster或者./redis-trib.rb:代表集群操作命令
  • create:代表是创建集群
  • --replicas 1或者--cluster-replicas 1 :指定集群中每个master的副本个数为1,此时节点总数 ÷ (replicas + 1) 得到的就是master的数量。因此节点列表中的前n个就是master,其它节点都是slave节点,随机分配到不同master

运行后的样子:

Redis持久化、集群_第36张图片

这里输入yes,则集群开始创建:

Redis持久化、集群_第37张图片

通过命令可以查看集群状态:

redis-cli -p 7001 cluster nodes

image-20210702181922809

2.4.5 测试

尝试连接7001节点,存储一个数据:

# 连接
redis-cli -p 7001
# 存储数据
set num 123
# 读取数据
get num
# 再次存储
set a 1

结果悲剧了:

Redis持久化、集群_第38张图片

集群操作时,需要给redis-cli加上-c参数才可以:

redis-cli -c -p 7001

这次可以了:

Redis持久化、集群_第39张图片

实操记录

[root@xwk tmp]# rm -rf 7001 7002 7003
[root@xwk tmp]# ls
hsperfdata_root  ks-script-aYmaht  mysql.sock  mysql.sock.lock  redis-6.2.4  s1  s2  s3  yum.log
[root@xwk tmp]# mkdir 7001 7002 7003 8001 8002 8003
[root@xwk tmp]# ls
7001  7002  7003  8001  8002  8003  hsperfdata_root  ks-script-aYmaht  mysql.sock  mysql.sock.lock  redis-6.2.4  s1  s2  s3  yum.log
[root@xwk tmp]# vim redis.conf
[root@xwk tmp]# echo 7001 7002 7003 8001 8002 8003 | xargs -t -n 1 cp redis.conf
cp redis.conf 7001
cp redis.conf 7002
cp redis.conf 7003
cp redis.conf 8001
cp redis.conf 8002
cp redis.conf 8003
[root@xwk tmp]# printf '%s\n' 7001 7002 7003 8001 8002 8003 | xargs -I{} -t sed -i 's/6379/{}/g' {}/redis.conf
sed -i s/6379/7001/g 7001/redis.conf
sed -i s/6379/7002/g 7002/redis.conf
sed -i s/6379/7003/g 7003/redis.conf
sed -i s/6379/8001/g 8001/redis.conf
sed -i s/6379/8002/g 8002/redis.conf
sed -i s/6379/8003/g 8003/redis.conf
[root@xwk tmp]# printf '%s\n' 7001 7002 7003 8001 8002 8003 | xargs -I{} -t redis-server {}/redis.conf
redis-server 7001/redis.conf
redis-server 7002/redis.conf
redis-server 7003/redis.conf
redis-server 8001/redis.conf
redis-server 8002/redis.conf
redis-server 8003/redis.conf
[root@xwk tmp]# ps -ef | grep redis
root       1622      1  0 21:30 ?        00:00:00 redis-server 0.0.0.0:7001 [cluster]
root       1624      1  0 21:30 ?        00:00:00 redis-server 0.0.0.0:7002 [cluster]
root       1630      1  0 21:30 ?        00:00:00 redis-server 0.0.0.0:7003 [cluster]
root       1636      1  0 21:30 ?        00:00:00 redis-server 0.0.0.0:8001 [cluster]
root       1642      1  0 21:30 ?        00:00:00 redis-server 0.0.0.0:8002 [cluster]
root       1648      1  0 21:30 ?        00:00:00 redis-server 0.0.0.0:8003 [cluster]
root       1660   1171  0 21:31 pts/0    00:00:00 grep --color=auto redis
[root@xwk tmp]# redis-cli --cluster create --cluster-replicas 1 192.168.145.130:7                                                                                 001 192.168.145.130:7002 192.168.145.130:7003 192.168.145.130:8001 192.168.145.13                                                                                 0:8002 192.168.145.130:8003
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 192.168.145.130:8002 to 192.168.145.130:7001
Adding replica 192.168.145.130:8003 to 192.168.145.130:7002
Adding replica 192.168.145.130:8001 to 192.168.145.130:7003
>>> Trying to optimize slaves allocation for anti-affinity
[WARNING] Some slaves are in the same host as their master
M: 857a696f133fa579174b9852d0535811889ef845 192.168.145.130:7001
   slots:[0-5460] (5461 slots) master
M: 5318bdca80e7a2cb5c56c513622f9b303d813a96 192.168.145.130:7002
   slots:[5461-10922] (5462 slots) master
M: 6b6419c1ffa152076981bd82d34327bdc2357393 192.168.145.130:7003
   slots:[10923-16383] (5461 slots) master
S: c65fd284e13246b09c91e585677a9bbc5b9d7067 192.168.145.130:8001
   replicates 5318bdca80e7a2cb5c56c513622f9b303d813a96
S: d310a56550b0c2a7103c59273051bc9f9faa4f1f 192.168.145.130:8002
   replicates 6b6419c1ffa152076981bd82d34327bdc2357393
S: 6f7e594955c03e06c58408fa1d9e6c31094f49b9 192.168.145.130:8003
   replicates 857a696f133fa579174b9852d0535811889ef845
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
.
>>> Performing Cluster Check (using node 192.168.145.130:7001)
M: 857a696f133fa579174b9852d0535811889ef845 192.168.145.130:7001
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
S: c65fd284e13246b09c91e585677a9bbc5b9d7067 192.168.145.130:8001
   slots: (0 slots) slave
   replicates 5318bdca80e7a2cb5c56c513622f9b303d813a96
M: 5318bdca80e7a2cb5c56c513622f9b303d813a96 192.168.145.130:7002
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
S: d310a56550b0c2a7103c59273051bc9f9faa4f1f 192.168.145.130:8002
   slots: (0 slots) slave
   replicates 6b6419c1ffa152076981bd82d34327bdc2357393
S: 6f7e594955c03e06c58408fa1d9e6c31094f49b9 192.168.145.130:8003
   slots: (0 slots) slave
   replicates 857a696f133fa579174b9852d0535811889ef845
M: 6b6419c1ffa152076981bd82d34327bdc2357393 192.168.145.130:7003
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
[root@xwk tmp]# redis-cli -p 7001 cluster nodes
857a696f133fa579174b9852d0535811889ef845 192.168.145.130:7001@17001 myself,master                                                                                  - 0 1700141729000 1 connected 0-5460
c65fd284e13246b09c91e585677a9bbc5b9d7067 192.168.145.130:8001@18001 slave 5318bdc                                                                                 a80e7a2cb5c56c513622f9b303d813a96 0 1700141728558 2 connected
5318bdca80e7a2cb5c56c513622f9b303d813a96 192.168.145.130:7002@17002 master - 0 17                                                                                 00141728659 2 connected 5461-10922
d310a56550b0c2a7103c59273051bc9f9faa4f1f 192.168.145.130:8002@18002 slave 6b6419c                                                                                 1ffa152076981bd82d34327bdc2357393 0 1700141728000 3 connected
6f7e594955c03e06c58408fa1d9e6c31094f49b9 192.168.145.130:8003@18003 slave 857a696                                                                                 f133fa579174b9852d0535811889ef845 0 1700141729066 1 connected
6b6419c1ffa152076981bd82d34327bdc2357393 192.168.145.130:7003@17003 master - 0 17                                                                                 00141729578 3 connected 10923-16383
[root@xwk tmp]# redis-cli -p 7001
127.0.0.1:7001> set num 123
OK
127.0.0.1:7001> get num
"123"
127.0.0.1:7001> set a 1
(error) MOVED 15495 192.168.145.130:7003
127.0.0.1:7001>
[root@xwk tmp]# redis-cli -c -p 7001
127.0.0.1:7001> set a 1
-> Redirected to slot [15495] located at 192.168.145.130:7003
OK
192.168.145.130:7003> exit
[root@xwk tmp]# redis-cli -c -p 7001
127.0.0.1:7001> set age 11
OK
127.0.0.1:7001> set name gk
-> Redirected to slot [5798] located at 192.168.145.130:7002
OK
192.168.145.130:7002>


你可能感兴趣的:(redis,缓存)