redis的数据都存放在内存中,如果没有配置持久化机制,重启之后就会全丢失了。需要开启持久化机制,将数据保存到磁盘上,当redis重启后,可以从磁盘上恢复。
两种持久化方式RDB和AOF
在指定时间内对数据记性快照保存,会缺失部分数据。
恢复方式 :
1.client端直接用命令BGSAVE或者SAVE创建一个内存快照
BGSAVE 调用fork来创建子进程,子进程负责写入快照磁盘中,而父进程仍然处理命令
SAVE 执行命令过程中,不再响应其他命令
配置文件 redis.conf,默认满足条件的触发
# 900秒之内至少一次写操作
save 900 1
# 300秒之内至少发生10次写操作
save 300 10
# 60秒之内发生至少10000次
save 60 1000
优点和缺点
优点 | 缺点 |
对性能影响最小 | 同步丢失数据 |
比AOF恢复要快 | 如果数据集非常大且CPU不够强(比如单核 CPU),Redis在fork子进程时可能会消耗相 对较长的时间,影响Redis对外提供服务的 能力。 |
记录每次对服务器数据读写的操作命令,服务器重启,就会执行这些命令恢复原始的数据。
方式:
BGREWRITEAOF命令可以触发日志重写或自动重写,废除对同一个Key历史的无用命令,重建当前数据集所需的最短命令序列。
意外中断,如果最后的命令只写了一部分,恢复时则会跳过它,执行后面完整的命令。
配置文件redis.cof
开启AOF持久化
appendonly yes
AOF策略调整
#每次有数据修改发生时都会写入AOF文件,非常安全非常慢
appendfsync always
#每秒钟同步一次,该策略为AOF的缺省策略,够快可能会丢失1秒的数据
appendfsync everysec
#不主动fsync,由操作系统决定,更快,更不安全的方法
appendfsync no
优点和缺点
优点 | 缺点 |
安全 | 文件体积大 |
容灾 | IO消耗高 |
易读,可修改 | 比RDB慢 |
持久化丢失的可能 :
RDB 方式
快照产生的策略,天生就不保证数据安全
AOF 持久化策略
默认每秒同步一次磁盘,可能会有1秒的数据丢失
每次修改都同步,数据安全可保证,但Redis高性能的特性全无
主从复制丢失的可能:
异步复制,存在一定的时间窗口数据丢失
网络、服务器问题,存在一定数据的丢失
首先我们要对内存分配有了解
内存分配
Strings类型:一个String类型的value最大可以存储512M。
Lists类型:list的元素个数最多为2^32-1个,也就是4294967295个。
Sets类型:元素个数最多为2^32-1个,也就是4294967295个。
Hashes类型:键值对个数最多为2^32-1个,也就是4294967295个
# 最大内存控制
maxmemory 最大内存阈值
maxmemory-policy 到达阈值的执行策略
内存压缩
#配置字段最多512个
hash-max-zipmap-entries 512
#配置value最大为64字节
hash-max-zipmap-value 64
#配置元素个数最多512个
list-max-ziplist-entries 512
#配置value最大为64字节
list-max-ziplist-value 64
#配置元素个数最多512个
set-max-intset-entries 512
#配置元素个数最多128个
zset-max-ziplist-entries 128
#配置value最大为64字节
zset-max-ziplist-value 64
#如果超出范围,redis将自动转换成正常大小
主动处理
( redis 主动触发检测key是否过期)每秒执行10次。
过程如下:
1. 从具有相关过期的密钥集中测试20个随机密钥
2. 删除找到的所有密钥已过期
3. 如果超过25%的密钥已过期,请从步骤1重新开始
被动处理:
1. 每次访问key的时候,发现超时后被动过期,清理掉
RDB方式
过期的key不会被持久化到文件中。
载入时过期的key,会通过redis的主动和被动方式清理掉。
AOF方式
当 redis 使用 AOF 方式持久化时,每次遇到过期的 key redis 会追
加一条 DEL 命令 到 AOF 文件,
也就是说只要我们顺序载入执行 AOF 命令文件就会删除过期的键。
Least recently used 最少使用
根据历史的访问记录来进行淘汰数据
核心思想:如果数据最近被访问过,那么将来被访问的几率也更高。
注意:Redis的LRU算法并非完整的实现,完整的LRU实现是因为这需要太多的内存。
方法:通过对少量keys进行取样(50%),然后回收其中一个最好的key。
配置方式: maxmemory-samples 5
Least Frequently Used
根据数据的历史访问频率来淘汰数据
核心思想:如果数据过去被访问多次,那么将来被访问的频率也更高。
Redis实现的是近似的实现,每次对key进行访问时,用基于概率的对数计数器来记录
访问次数,同时这个计数器会随着时间推移而减小。
Morris counter算法依据:
https://en.wikipedia.org/wiki/Approximate_counting_algorithm
启用LFU算法后,可以使用热点数据分析功能。( redis-cli --hotkeys )
配置文件:maxmemory-policy noeviction
动态设置:maxmemory-policy noeviction
回收策略 | 备注 |
noeviction | 客户端尝试执行会让更多内存被使用的命令直接报错 |
allkeys-lru | 在所有key里执行LRU算法 |
volatile-lru | 在所有已经过期的key里执行LRU算法 |
volatile-lfu | 使用过期集在密钥中使用近似LFU进行驱逐 |
allkeys-lfu | 使用近似LFU逐出任何键 |
allkeys-random | 在所有key里随机回收 |
volatile-random | 在已经过期的key里随机回收 |
volatile-ttl | 回收已经过期的key,并且优先回收存活时间(TTL)较短的键 |
缓存击穿
某一热点key,洪峰期突然缓存key失效,造成直击数据库
解决方案:
1.设置热点key永不过期 2.增加互斥锁(拿到锁的才有资格去查询数据库)
缓存穿透
查询一个不存的key,导致redis不可用,穿透造成数据库压力
解决方案:
1.增加检验参数
2.从nigix增加配置项,对单个key每秒访问的次数超过阀值,就把IP名单拉黑
3.布隆过滤器,提前判断值存在不存在,有误差率
4.设置不存在key值,并设置过期的时间。
缓存雪崩
洪峰期大面积缓存key失效或数据库挂掉,导致海量数据请求去查询室数据库
解决方案:
1.批量往redis存数据的时候,key的失效时间设置随机值,保证在同一时间不会大面积失效
2.集群部署,均匀的分布在不同的redis库中也能避免
3.设置热点数据永远不过期,有更新操作更新缓存就好
4.缓存穿透和缓存击穿都是造成雪崩的前提
5.缓存降级