Redis 持久化策略:
redis 持久化数据分两种方式:1. rdb 2. aof
rdb 方式:当执行 save 或者 bgsave 指令时,redis 会记录当前时刻内存缓存的数据快照并将数据写入到文件后缀为 rdb 的文件中,如果使用的是 save 指令持久化数据会导致阻塞,因为它使用 redis 主线程做数据持久化,如果使用 bgsave 指令持久化数据会开启子线程,由子线程做数据持久化,当子线程持久化数据时,主线程会复制一份完成的数据,后续主线程处理新的请求修改缓存数据,但是只修改新副本中的数据,redis 默认开启 rdb 方式持久化数据,可以在配置文件中配置持久化策略,如:save 10 2 十秒内修改两次数据就做数据持久化
aof 方式:aof 指令追加方式持久化数据,redis 执行数据操作指令时会将操作指令追加到 aof 文件中,aof 持久化数据需要手动开启与配置持久化策略,如:appendfsync always 每执行一次写命令,立即记录指令到aof文件, appendfsyn everysec 每秒同步一次指令到aof 文件中 , appendfsync on 操作指令执行后先放入aof 缓冲区,由操作系统决定何时将缓冲区指令写入 aof 文件中
rdb 与 aof 两种缓存方式对比:
rdb 使用二进制文件持久化数据,文件体积小,服务宕机数据恢复快,数据完整度低
aof 保存指令信息持久化数据,文件体积大,服务宕机数据恢复慢,数据完整度高
也可以使用 rdb、aof 混合模式做数据持久化,在 redis 5.0 版本默认开启混合持久化,如果没有开启,可以在 redis.conf 文件中配置 aof-use-rdb-preamble yes 信息开启持久化,混合持久化数据时,会先将内存中的数据以快照的方式储存到 aof 文件的头部,后续执行的操作指令会追加到 aof 文件中
缓存穿透:
请求的数据在 redis 和数据库中都没有,如果有大量的请求获取该数据,这些请求都会去数据库查询数据,导致数据库压力过大可能造成服务性能变差
两种解决方式:1.缓存空数据 2.使用布隆过滤器
缓存击穿:
缓存的热点数据过期在缓存数据重建的过程中,有大量的请求打到数据库导致数据库压力过大
解决方案:
1. 使用互斥锁,当一个请求获取缓存数据时发现缓存数据过期,在查询数据库之前先获取锁资源,然后去查询数据库并将数据缓存到 redis 服务中,其它未获取到锁资源的请求,可多次重试获取缓存信息
2. 缓存数据逻辑过期,缓存数据不设置过期时间进行逻辑处理,缓存数据时可以添加一个过期时间属性,如果有请求获取数据处理过期时间发现数据已过期,获取锁资源去数据库拿到新 数据然后将新数据写到缓存中,处理新数据的逻辑,可以开启子线程完成,不需要主线程等待,主线程可以先返回过期的数据给用户,未获取到锁资源的请求都可以返回过期数据给用户,前提当前功能对数据强一致性要求不高
方案1 数据实时处理但会出现请求线程阻塞问题性能差,方案2 数据有延迟但可用性强性能好
缓存雪崩:
在某一时刻批量的缓存数据过期,出现大量的请求打到数据库导致数据库的压力过大
解决方案:对不同的缓存数据设置过期时间时加上随机值 , 让缓存数据不在某一时间大量过期
Redis 数据双写:
使用 redis 缓存数据,当修改数据库的数据需要更新 redis 中的缓存信息 ,如果更新缓存数据操作不当可能会导致缓存数据为脏数据,例如:线程1回去缓存数据发现缓存数据已过期,然后读取数据库中的数据,在数据还没有回写到缓存时,线程2修改了数据库中的数据然后将新的数据缓存到redis 中,随后线程1将数据库中旧的数据覆盖了缓存数据,出现数据库数据和缓存数据不一致缓存数据为脏数据问题
解决方案:
1. 使用 redission 读写锁,在修改数据时先加上写锁,然后再去修改数据库数并将新的数据写到缓存中再释放锁,释放锁之前请他线程不能读取或修改数据,可以多次尝试获取缓存数据
2. 如果对数据实时性要求不高可以异步缓存数据,使用 MQ、Canal 通知缓存服务缓存数据,这样做数据有延迟
Redis 分布式锁:
redis 分布式锁主要使用 setnx 指令,如果数据添加成功获取到分布式锁
在使用分布式锁一定要设置数据过期时间防止死锁问题,但是过期时间设置不当,可能出现第一个获取锁资源的线程任务还没有处理完,第二个线程获取到锁信息违背了分布式锁的互斥性,可以使用 redission 框架实现分布式锁,redisson 使用 Lua 脚本创建锁并开启子线程监控锁信息,在没有释放锁之前帮助延续锁的持有时间,redisson 提供的锁是一个可重入锁,在创建锁信息时会记录当前获取锁的线程 id 与 获取锁的次数,当线该程再次获取锁会比对线程信息,如果是同一个线程获取锁的次数加一,在释放锁时进行减一为零时删除锁信息
Redis 数据过期删除策略:
设置过期时间的缓存数据,如果过期了 redis 提供了两种删除策略:
1. 惰性删除:在下次访问数据时会判断当前数据是否过期,如果数据过期删除数据返回空,没有过期返回数据
2. 定期删除:每隔一定的时间查找删除过期数据
Redis 数据淘汰策略:
redis 缓存数据的内存是有限的,如果内存满了,redis 提供了多种删除数据的策略:
1. noeviction 不删除数据 ,如果添加新的数据直接抛异常
2. allkeys - random 所有数据中随机删除一些数据
3. volatile - ttl 删除设置数据剩余过期时间最少的数据
4. volatile - random 随机删除设置过期时间的数据
5. allkeys - lru 删除所有数据中最近最少访问的数据
6. volatile - lru 删除设置过期时间数据中最少使用的数据
7. allkeys - lfu 删除所有数据中使用次数最少的数据
8. volatile - lfu 删除设置过期时间数据中使用次数最少的数据