Redis 基础: https://blog.yexca.net/archives/157/
Redis 分布式缓存: 本文
引言
所以这俩文章同时写的但却过了一年才发是吧
其实是我当时有三个要写的来着,但每次想起来看的时候都忘了要写啥,就过了快一年。。。
问题
单机 Redis 存在
- 数据丢失问题:实现 Redis 数据持久化
- 并发能力问题:搭建主从集群,实现读写分离
- 存储能力问题:搭建分片集群,利用插槽机制实现动态扩容
- 故障恢复问题:利用 Redis 哨兵,实现健康检测和自动恢复
Redis 持久化
Redis 持久化有两种方案:RDB 与 AOF
RDB 持久化
RDB 全称 Redis Database Backup file (Redis 数据备份文件),也叫做 Redis 数据快照。简单来说就是把内存中所有数据都记录到磁盘中。当 Redis 实例故障重启后,从磁盘读取快照文件,恢复数据。快照文件成为 RDB 文件,默认保存在运行目录
RDB 会在以下四种情况下执行:
- 执行 save 命令:立即执行,会导致主进程执行 RDB,其他所有命令被阻塞。仅在数据迁移时可能用到
- 执行 bgsave 命令:异步执行,开启独立进程完成 RDB,主进程可以持续处理用户请求,不受影响
- Redis 停机时:停机时会执行一次 save 命令
- 触发 RDB 条件时:配置文件配置,如下
# 900秒内,如果至少有1个key被修改,则执行bgsave , 如果是save "" 则表示禁用RDB
save 900 1
save 300 10
save 60 10000
其他配置
# 是否压缩 ,建议不开启,压缩也会消耗cpu,磁盘的话不值钱
rdbcompression yes
# RDB文件名称
dbfilename dump.rdb
# 文件保存的路径目录
dir ./
RDB 原理
bgsave 开始时会 fork 主进程得到子进程,子进程共享主进程的内存数据。完成 fork 后读取内存数据并写入 RDB 文件
fork采用的是 copy-on-write 技术:
- 当主进程执行读操作时,访问共享内存
- 当主进程执行写操作时,则会拷贝一份数据,执行写操作
RDB 的缺点:
- 执行间隔时间长,两次 RDB 之间写入数据有丢失的风险
- fork 子进程、压缩、写出 RDB 文件都比较耗时
AOF 持久化
AOF 全称 Append Only File (追加文件),Redis 处理的每一个写命令都会记录在 AOF 文件,可以看作命令日志文件
AOF 默认是关闭的,修改配置文件开启
# 是否开启AOF功能,默认是no
appendonly yes
# AOF文件的名称
appendfilename "appendonly.aof"
记录频率也可以通过 redis.conf 配置
# 表示每执行一次写命令,立即记录到AOF文件
appendfsync always
# 写命令执行完先放入AOF缓冲区,然后表示每隔1秒将缓冲区数据写到AOF文件,是默认方案
appendfsync everysec
# 写命令执行完先放入AOF缓冲区,由操作系统决定何时将缓冲区内容写回磁盘
appendfsync no
配置项对比:
配置项 | 刷盘时机 | 优点 | 缺点 |
---|---|---|---|
always | 同步刷盘 | 可靠性高,几乎不丢数据 | 性能影响大 |
everysec | 每秒刷盘 | 性能适中 | 最多丢失 1 秒数据 |
no | 操作系统控制 | 性能最好 | 可靠性差,可能丢失大量数据 |
文件重写
因为是记录命令,AOF 文件会比 RDB 大很多,而且 AOF 会记录对同一个 key 的多次写操作,但只有最后一次写操作才有意义。通过执行 bgrewriteaof
命令,可以让 AOF 文件执行重写功能,用最少的命令达到相同效果
假设原先命令为:
set num 123
set name jack
set num 666
重写后:
mset name jack num 666
Redis 也会在触发阈值时自动重写 AOF 文件,在配置文件配置
# AOF文件比上次文件 增长超过多少百分比则触发重写
auto-aof-rewrite-percentage 100
# AOF文件体积最小多大以上才触发重写
auto-aof-rewrite-min-size 64mb
RDB 与 AOF 对比
RDB 与 AOF 各有自己的优缺点,如果对数据安全性要求过高,在实际开发中往往会结合两者来使用
RDB | AOF | |
---|---|---|
持久化方式 | 定时对整个内存做快照 | 记录每一次执行的命令 |
数据完整性 | 不完整,两次备份之间会丢失 | 相对完整,取决于刷盘策略 |
文件大小 | 会有压缩,文件体积小 | 记录命令,文件体积很大 |
宕机恢复优先级 | 很快 | 慢 |
数据恢复优先级 | 低,因为数据完整性不如 AOF | 高,因为数据完整性更高 |
系统资源占用 | 高,大量 CPU 和内存消耗 | 低,主要是磁盘 I0 资源但 AOF 重写时会占用大量 CPU 和内存资源 |
使用场景 | 可以容忍数分钟的数据丢失,追求更快的启动速度 | 对数据安全性要求较高常见 |
Redis 主从架构
单节点 Redis 的并发能力是有上限的,要进一步提高 Redis 的并发能力,就需要搭建主从集群,实现读写分离
按照集群
基于 CentOS7
参考上图一共三个节点,部署在同一个机子,端口为 7001(master)、7002、7003
首先创建目录
cd /tmp
mkdir 7001 7002 7003
如更改配置,需恢复默认的 RDB 模式
# 开启RDB
# save ""
save 3600 1
save 300 100
save 60 10000
# 关闭AOF
appendonly no
拷贝配置文件到每个实例目录
# 方式一
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
修改每个实例的端口,工作目录(端口修改,rdb 文件保存位置修改)
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
修改 IP,每个目录都要改 (替换 ip_address)
# 逐一执行
sed -i '1a replica-announce-ip ip_address' 7001/redis.conf
sed -i '1a replica-announce-ip ip_address' 7002/redis.conf
sed -i '1a replica-announce-ip ip_address' 7003/redis.conf
# 或者一键修改
printf '%s\n' 7001 7002 7003 | xargs -I{} -t sed -i '1a replica-announce-ip ip_address' {}/redis.conf
启动
# 第1个
redis-server 7001/redis.conf
# 第2个
redis-server 7002/redis.conf
# 第3个
redis-server 7003/redis.conf
停止
printf '%s\n' 7001 7002 7003 | xargs -I{} -t redis-cli -p {} shutdown