目录
1、Redis持久化
- 优缺点对比
- 实际配置
- 根据RDB文件的恢复过程
2、Redis读写分离架构
- 注意事项
- 复制流程
- 数据丢失场景
- 哨兵
3、Redis集群架构
- 数据的负载均衡算法
- 实际操作
- 主备切换过程
4、缓存架构
- 一般缓存架构
- 多级缓存架构
5、数据清除策略
- 配置
- 流程
Redis持久化
持久化策略共提供了两种
-
RDB 全量备份
每隔一个时间间隔做Redis的一份快照,记录当前Redis中的全都数据 -
AOF 增量备份
记录Redis的每一次操作到AOF文件
AOF流程:
Redis只有一个AOF文件,在Redis和AOF文件间存在一个OSCache系统级缓存,Redis每次写操作先存储在OSCache中,每隔一段时间执行fsync操作,将OSCache中的数据再写入磁盘中的AOF文件,这时才真正的存储在磁盘上。
Redis的内存是一定量的,AOF则是记录每条数据的操作,所以会逐渐变大。当Redis执行LRU策略淘汰某些数据时,AOF中记录的数据就会过期,所以当AOF到一定程度时会有rewrite操作。rewrite操作会根据当前Redis中的数据,重新构建一个新AOF文件,以清除过期失效的记录缩小AOF文件大小,构建完成后替换旧的AOF文件。
优缺点对比
RDB优点:适合冷备、性能高(不必一条条记录写磁盘)、数据恢复快
RDB缺点:丢数据多(时间间隔内的数据)、数据量多时恢复会有延迟
AOF优点:最多丢时间间隔内的数据(间隔比RDB短)、append-only模式不需寻址写入AOF文件性能高,文件不易破损
AOF缺点:相同情况下AOF文件大于RDB文件大小、拖慢Redis的QPS、数据恢复慢(重放操作)
实际配置
RDB
redis.conf文件,SNAPSHOTTING节点下设置RDB的相关参数
默认设置
save 900 1
save 300 10
save 60 1000
即:每隔60秒超过1000个key发生变更,则生成一个dump.rdb文件
配置文件内可配置多个检查点
生成的dump.rdb文件在配置的dir
目录下,新文件覆盖旧文件
安全退出Redis,会自动触发生成当前Redis的dump.rdb文件
AOF
redis.conf文件,APPEND ONLY MODE节点下设置AOF的相关参数
RDB是默认打开的,而AOF是默认关闭
appendonly yes 打开AOF
若Redis重启且AOF和RDB都开启的情况下,优先AOF恢复(数据完整性较RDB好)在dir
目录下查找AOF文件进行恢复
fsync操作的设置,会影响数据的丢失量
appendfsync always 每写入一条数据,立即执行fsync操作将数据写入磁盘,性能差、吞吐量低
appendfsync everysec 每秒将OSCache中的数据刷入磁盘,QPS在万级别,默认项
appendfsync no 数据进入OSCache后,由OS决定刷入磁盘的时机
rewrite策略,控制AOF文件不至于无限增长
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
较上次rewrite的AOF文件大小,增长比例达到100%,且AOF文件大于min-size大小,则触发rewrite操作
rewrite流程:
- Redis fork一个子进程,基于当前内存的数据构建日志,写入新AOF文件中。
- 此时Redis主进程能继续接收外部的写操作,并将操作记录存入一块内存同时写入旧AOF文件中。
- 子进程完成后,主进程将内存中新记录追加到新AOF文件中
- 新AOF文件替换旧AOF文件
AOF 文件修复
因为AOF文件采用append-only模式写入,所以文件破损只会发生在文件尾部
redis-check-aof --fix [file] 通过此命令进行AOF的文件修复
RDB全量备份与AOF的rewrite不会同时进行,若发生则等待前一操作完成后执行(磁盘IO开销太大)
根据RDB文件的恢复过程
1.关闭AOF配置项,否则默认根据AOF恢复,如没有发现AOF文件则会生成一份空的AOF文件,并根据空的AOF文件恢复
2.拷贝RDB文件到目录,重启Redis,完成恢复
3.热修改开启AOF,这时生成的AOF文件会存储当前数据,但通过热修改配置的方式在配置文件内并没有实际修改
4.关闭Redis,手动修改配置开启AOF,再次重启Redis
Redis读写分离架构
Redis缓存主要应对的是读请求场景,对于未命中项则会请求到数据库,MySQL正常的QPS在1~2K。要想达到高并发,需要将读请求在Redis缓存层处理掉。
单机Redis可承载万级的QPS(视业务场景、机器而定),要承载更高的并发需要进行读写分离,master node只负责写操作,slave node负责读操作,两者数据一致。当并发量增加时,可横向扩展增加slave node来分摊QPS。
注意事项
-
master node采用异步的方式复制数据到slave node,不会影响master node的正常操作
-
slave node复制数据期间会提供对外的读操作,只不过数据复制完成前提供的数据是旧数据。复制完成后,删除旧数据加载新数据阶段,会暂停对外的服务。
-
采用主从架构需要对master node做持久化,否则master node故障重启后(侦测机制还未触发)数据丢失,将会影响所有的slave node
-
slave node不会过期key,master node过期key后会del通知给slave node
-
master node和slave node之间通过心跳相互联系
-
一个master node可以配置多个slave node,slave node之间也可以互相连接
复制流程
slave node启动时,读取conf配置slaveof
中master node的IP和port,slave node内部的定时任务,定期检查是否有新的master node需要连接和复制,并进行socket连接
slave node发送ping命令给master node,若master node设置了requirepass
,则slave node必须发送masterauth口令进行认证
如果是第一次连接会触发full resynchronization,master node采用异步的方式复制数据到slave node;如果是重连,master node仅会复制slave node缺少的数据。
开始full resynchronization时,master node会用后台线程做一份RDB的快照文件,slave node会将RDB文件写入自己的磁盘后再加载到内存。期间master node的写操作会记录在内存,master node会将内存中的写命令发送给slave node
master node和slave node都会维护一个offset,且在不断累加,记录当前的数据。slave node会定期上报master node自己的offset,master node也会记录各个slave node的offset,用来知晓相互间的数据差异。
若在复制的过程中连接断开重连,slave node可以从offset的位置继续复制,如果找不到对应的offset则会执行resynchronization;slave node也会记录master run id,若发现master run id不同,可能是master node重启或发生变化,需要做全量复制
配置文件redis.conf中可以设置生成的RDB文件是否落在本地磁盘
repl-diskless-sync no 是否开启无磁盘化复制
repl-diskless-sync-delay [] 延迟复制,等待更多的slave node连接
参数配置
slaveof [ip] [port] 填入master node的信息
slave-read-only yes 默认开启slave node只读
数据丢失场景
异步复制 集群脑裂解决方法
min-slaves-to-write 1 最少要写入slave node的数量为1
min-slaves-max-lag 10 master node和slave node间数据延迟不能超过10秒
此配置默认未开启
此配置只是降低数据损失量,剩余要client做降级操作减少损失
哨兵
哨兵是分布式的架构,最少有3个实例,以保证自己的健壮性。
哨兵只保证Redis的高可用,不保证数据的零丢失
哨兵间的通讯通过Redis的pub/sub系统实现
功能
- 集群监控 监控Redis中master node和slave node是否正常工作
- 消息通知 Redis实例故障时发送通知
- 故障转移 如果master node故障,会选举新master node
- 配置中心 故障转移时会将新配置项通知各个端
工作流程
哨兵有两种失败状态,1个哨兵认为master node挂了就是sdown(主观宕机),quorum数量个哨兵认为master node挂了就是odown(客观宕机)。
当哨兵ping master node响应时间超过设置的down-after-milliseconds时进入sdown状态
如果master node被认为odown,且有majority数量的哨兵允许主备切换,就会有一个哨兵执行主备切换的操作,选举一个slave node作为新master node
考虑因素包括:与master node断开的时长、slave node的优先级、offset值、run id值
配置参数
sentinel.conf
哨兵可以监控多个Redis的主从架构
sentinel monitor [架构名] [ip] [quorum] 监控的主从架构信息
sentinel down-after-milliseconds [架构名] 60000 超过设置时间认为sdown
sentinel failover-timeout [架构名] 180000 执行故障转移的超时时间
sentinel parallel-sync [架构名] 1 并行同步数,新选举的master node,每次同步slave node的数据量,数据同步完成后才会执行后面slave node的同步
port [] 端口号
bind [ip] 绑定本机IP
daemonize yes 后台执行
logfile /var/log/sentinel/*.log 设置日志文件
Redis集群架构
-
读写分离架构:master node负责写操作,slave node负责读操作,配合哨兵能够达到高可用。
-
集群架构:存在多个master node,每个master node上可挂载多个slave node。各个master node之间数据不同,能够提供读写操作。当master node挂掉后,slave node顶上以达到高可用。
读写分离的架构能够存储的数据量仅为master node的内存容量,在海量数据场景下会产生瓶颈,因此在海量数据场景下适用集群架构
数据的负载均衡算法
Hash算法(散列算法)用一种较短的信息来保证内容唯一性的算法。在Redis集群架构下如果某一节点挂了,则会导致全部信息失效。
一致性Hash算法,节点之间采用环形,在Redis集群架构下如果某一节点挂了,则只会丢失此节点数据。热点问题采用虚拟节点来负载均衡
Hash slot算法,数据存储在slot上,slot存储在节点上,如果某一节点挂了,数据是寻找slot而不是节点,且挂掉的节点会将本节点上的slot迁移到其他节点。
实际操作
配置参数
cluster-enabled yes 启动集群架构,不可同时开启读写分离架构
cluster-config-file [配置文件] 指定配置文件
cluster-node-timeout [] 节点超时时长,超时则主备切换
port []
daemonize yes
pidfile /var/run/redis_[port].pid
dir /var/redis/[port]
logfile /var/log/redis/[port].log
bind [ip]
appendonly yes
集群操作
redis-trib.rb create --replicas [slave node数量] [ip:port] [ip:port] [ip:port] [ip:port]... 启动cluster
redis-trib.rb add-node [ip:port]... 扩容master
redis-trib.rb reshard [ip:port] 会有交互提示输入数据迁移的参数
redis-trib.rb add-node --slave --master-id [id] [ip:port] 给master节点增加slave
redis-trib.rb del-node [ip:port] [id] 删除节点
master node不存在slot时,cluster会将其slave node挂到其他master node上
cluster会将冗余的slave node分配给其他master node,以保证高可用
主备切换过程
各个节点保存集群元数据,节点间采用gossip协议进行通讯,通过节点间不断的通讯以保持整个集群的数据完整性
当一个节点认为另一个节点宕机了(响应时间超过cluster-node-timeout
)称为pfail(主观宕机),多个节点认为一个节点宕机了称为fail(客观宕机)
对于宕机的master node,从其slave node中选取一个切换为master node
筛选的条件和哨兵类似:断开连接时间(时间超过cluster-node-timeout
*cluster-slave-validity-factory
的slave node没有资格参见选举)、priority、offset、run id
缓存架构
一般缓存架构
1.用户发起请求
2.读请求发起后被web服务器转发到web服务上
3.web服务先向Redis缓存查询
4.数据命中则将数据返回给用户
5.未命中则去数据库查询数据
6.数据命中后返回给web服务
7.web服务接收到数据后将数据返回给用户,同时缓存数据
多级缓存架构
缓存操作
- 同步缓存操作
1.用户向XX服务发送写请求
2.XX服务将数据同步更新到DB和Redis缓存
- 异步缓存操作
1.用户向XX服务发送写请求
2.XX服务将数据更新到DB同时向MQ发送消息
3.web服务接收到消息后,将数据写到本地缓存和Redis缓存中
读取操作
1.用户向web服务器发送读请求
2.在web服务器缓存中命中则返回,否则向Redis缓存请求数据
3.Redis缓存命中则返回数据
4.web服务器接收到Redis缓存中的数据则返回,否则向web服务发起读请求
5.web服务在堆缓存中查找数据,命中则返回并缓存到Redis缓存
6.web服务在堆缓存中未命中数据,则向DB请求数据
7.DB将数据返回给web服务
8.web服务拿到数据后,将数据在堆缓存、Redis缓存中保存,并返回web服务器
web服务器Nginx本地缓存主要存储热点数据,避免不必要的访问网络开销
Redis分布式大规模缓存,对应的是海量离散数据
web服务的堆缓存是为了避免Redis宕机,导致web服务器大量的请求涌入,打死DB(虽然效果甚微,总比没有要强)
数据清除策略
-
一种是对key设置存活时间(TTL),当访问的key超过存活时间,则返回null并删除本地数据
-
另一种则是存储的数据量超过了最大设置量
以下内容为第二种策略
配置
maxmemory 设置数据清除策略开始的大小
maxmemory-policy 数据满是所执行的策略
noeviction 拒绝写入
allkeys-lru 所有key执行LRU
volatile-lru 仅对设置了存活时间(TTL)的key执行LRU
allkeys-random 随机删除key
volatile-random 随机挑选设置了存活时间(TTL)的key删除
volatile-ttl 移除TTL较短的key
流程
1.外部有写入请求
2.检查是否超过maxmemory限制,是则执行maxmemory-policy策略清除部分数据
3.执行写入操作
常用策略:allkeys-lru
Redis的LRU清除策略是近似的LRU算法,它通过采样采集数据进行处理而非全量数据,采样参数maxmemory-sample
网友评论