redis单节点存在的问题

reids持久化
1.RDB持久化
通过对数据做快照的方式来实现持久化,将内存中的数据存储到磁盘中,在数据需要恢复的时候通过快照进行恢复。
RDB持久化在四种情况下会执行:
-
执行save命令
-
执行bgsave命令
-
Redis停机时
-
触发RDB条件时
RDB的设置和使用
在redis-cli中使用RDB(在主线程中执行)
#产生对应的RDB文件快照
save
效果图为下:

在执行save操作时会堵塞当前的主线程,会阻塞redis当前的其他操作。
在redis-cli中使用RDB(在子线程中执行)
#异步完成RDB操作
bgsave
效果图为下:

设置RDB配置(redis.conf中设置)
RDB触发条件设置
#在10秒内有100key对应的值发生改变时进行RDB
# save "间隔" "key的修改次数"
save 300 10
效果图为下:

RDB的其他配置
#快照压缩,占用CPU,减少磁盘开销
rdbcompression yes
#设置RDB的文件,也就是生成快照的名字和使用快照恢复数据时对应的快照名
dbfilename dump.rdb
效果图为下:
RDB的执行原理
redis的操作是单线程的,主线程通过页表来映射在物理内存中的对应内存块,在执行RDB的子线程中通过相同的页表来读取对应映射的内存块,从而生成对应的RDB快照。
在子线程执行读取操作时,主线程可能会同时执行增删改操作,这会导致脏读的情况,为了防止这种情况,真正的物理内存块设置了只读的权限。
在主线程中为了能够正常的进行增删改操作,通过复制对应的内存块中的数据,在该数据副本中进行增删改的操作,将页表中的关系映射到新的数据副本上。子进程中的页表不会马上更新,所以子进程的操作不会受到影响。

RDB的缺点
-
RDB执行间隔时间长,两次RDB之间写入数据有丢失的风险。
-
fork子进程、压缩、写出RDB文件都比较耗时。
2.AOF持久化
AOF全称为Append Only File(追加文件),通过创建AOF文件将在该数据库中执行的所有指令都记录到AOF文件中,通过AOF文件对数据进行恢复。
AOF的设置和使用
AOF的开启和文件名设置
#开启AOF
appendonly yes
#设置AOF文件名
appendfilename "appendonly.aof"
效果图为下:

AOF的模式设置
#总是执行,也就是在每次执行指令时就进行AOF
appendfsync always
#每过一秒执行一次AOF(默认使用策略)
appendfsync everysec
#不进行AOF,执行AOF由系统决定
appendfsync no
对应效果图为下:

三种策略对比

AOF文件重写(文件压缩)
在redis.conf中设置AOF重写触发条件
# AOF文件比上次文件 增长超过多少百分比则触发重写(比上次增加100触发重写)
auto-aof-rewrite-percentage 100
# AOF文件体积最小多大以上才触发重写 (体积大于64mb触发重写)
auto-aof-rewrite-min-size 64mb
效果图为下:

RDB和AOF对比

redis主从(集群最少三个节点)
docker下载redis镜像
docker pull redis
在服务器上创建对应的目录用于给redis的配置文件和持久化文件挂载。
#集群主节点1的data文件和conf文件映射
mkdir -p /mydata/redis/cluster/node1/data
mkdir -p /mydata/redis/cluster/node1/conf
touch /mydata/redis/cluster/node1/conf/redis.conf
#集群主节点2的data文件和conf文件映射
mkdir -p /mydata/redis/cluster/node2/data
mkdir -p /mydata/redis/cluster/node2/conf
touch /mydata/redis/cluster/node2/conf/redis.conf
#集群主节点3的data文件和conf文件映射
mkdir -p /mydata/redis/cluster/node3/data
mkdir -p /mydata/redis/cluster/node3/conf
touch /mydata/redis/cluster/node3/conf/redis.conf
#集群主节点4的data文件和conf文件映射
mkdir -p /mydata/redis/cluster/node4/data
mkdir -p /mydata/redis/cluster/node4/conf
touch /mydata/redis/cluster/node4/conf/redis.conf
创建redis节点1的容器和redis节点2的容器(端口记得开放)
#redis节点1容器
docker create --name redis-node1 -v /mydata/redis/cluster/node1/data:/data \
-v /mydata/redis/cluster/node1/conf/redis.conf:/etc/redis/redis.conf \
-p 16379:6379 redis --cluster-enabled yes \
--cluster-config-file redis-node1.conf
#redis节点2容器
docker create --name redis-node2 -v /mydata/redis/cluster/node2/data:/data \
-v /mydata/redis/cluster/node2/conf/redis.conf:/etc/redis/redis.conf \
-p 26379:6379 redis --cluster-enabled yes \
--cluster-config-file redis-node2.conf
#redis节点3容器
docker create --name redis-node3 -v /mydata/redis/cluster/node3/data:/data \
-v /mydata/redis/cluster/node3/conf/redis.conf:/etc/redis/redis.conf \
-p 36379:6379 redis --cluster-enabled yes \
--cluster-config-file redis-node3.conf
#redis节点4容器
docker create --name redis-node4 -v /mydata/redis/cluster/node4/data:/data \
-v /mydata/redis/cluster/node4/conf/redis.conf:/etc/redis/redis.conf \
-p 46379:6379 redis --cluster-enabled yes \
--cluster-config-file redis-node4.conf
启动两个容器
docker start redis-node1 redis-node2 redis-node3 redis-node4

查看容器运行状态
docker ps
效果图为下:

设置集群关系(主从关系,最少六个节点,以上述方式创建六个节点)
分别查看redis-node1至redis-node6的IP地址。
#查看redis节点1的信息
docker inspect redis-node1
#查看redis节点2的信息
docker inspect redis-node2
#查看redis节点3的信息
docker inspect redis-node3
#查看redis节点4的信息
docker inspect redis-node4
查看的效果图为下:
redis-node1

redis-node2

redis-node3

创建集群
redis-cli --cluster create 172.17.0.3:6379 172.17.0.4:6379 172.17.0.5:6379 172.17.0.6:6379 172.17.0.7:6379 172.17.0.8:6379 --cluster-replicas 1
效果图为下:

此时三个节点都是主节点。
进入某个redis节点中查看集群信息
#进入容器
docker exec -it "id" /bin/bash
#进入redis服务端
redis-cli
#查看集群情况
cluster nodes
效果图为下:

设置主从关系就是通过 --cluster-replicas 1来控制,如果为1,也就是主节点和从节点的个数为1:1。
主从数据同步原理
主从第一次建立连接时,会执行全量同步,将master节点的所有数据都拷贝给slave节点。

-
Replication Id:简称replid,是数据集的标记,id一致则说明是同一数据集。每一个master都有唯一的replid,slave则会继承master节点的replid(用于判断数据是否为第一次同步)
-
offset:偏移量,随着记录在repl_baklog中的数据增多而逐渐增大。slave完成同步时也会记录当前同步的offset。如果slave的offset小于master的offset,说明slave数据落后于master,需要更新。(判断上次数据同步到的位置)
master判断一个节点是否是第一次同步的依据,就是看replid是否一致。

在第二阶段使用的快照的数据同步,也就是RDB。
增量同步
此时数据无需完全同步,只需要从偏移量的位置向后同步到终点即可。

repl_backlog中存放数据执行的指令,在数据同步时从当前的偏移量开始的指令用于数据同步。
(有点类似AOF)
repl_backlog原理
这就要说到全量同步时的repl_baklog文件了。

这个文件是一个固定大小的数组,只不过数组是环形,也就是说角标到达数组末尾后,会再次从0开始读写,这样数组头部的数据就会被覆盖。(是个闭环)
epl_baklog中会记录主节点redis中数据存储到的偏移量,也会记录从节点在epl_baklog中数据同步到的偏移量,只要二者偏移量相同就说明当前的数据已经是同步的了,如果偏移量之间还有差距说明当前数据还尚未同步。
特殊情况 :从节点宕机后数据没有即使同步,主节点的偏移量越过从节点的偏移量,导致部分指令被覆盖,最终数据发生丢失。

解决方案:进行全量同步。