- 持久化
- 缓存雪崩
- 缓存穿透
- 缓存击穿
- 缓存预热
持久化
Redis的储存形式:一份在内存、一份在磁盘。内存的是最新的;磁盘里的会隔一段时间更新。
Redis持久化方式:
RDB:快照方式;将某⼀个时刻的内存数据,以⼆进制的⽅式写⼊磁盘;
AOF:文件追加方式;记录所有的操作命令,并以⽂本的形式追加到⽂件中;
RDB、AOF结合:混合持久化方式;Redis 4.0 之后新增的⽅式,混合持久化是结合了 RDB 和 AOF 的优点,在写⼊的时候,先把当前的数据以 RDB 的形式写⼊⽂件的开头,再将后续的操作命令以 AOF 的格式存⼊⽂件,这样既能保证 Redis 重启时的速度,⼜能减低数据丢失的⻛险。
如何切换呢?
redis-cli 命令⾏中执⾏ config set aof-use-rdb-preamble yes 来开启混合持久化,当开启混合持久化时 Redis 就以混合持久化⽅式来作为持久化策略;当没有开启混合持久化的情况下,使⽤ config set appendonly yes 来开启 AOF 持久化的策略,当 AOF 和混合持久化都没开启的情况下默认会是 RDB 持久化的⽅式。
优缺点:
缓存雪崩
缓存雪崩是指在短时间内,有⼤量缓存同时过期,导致⼤量的请求直接查询数据库,从⽽对数据库造成了巨⼤的压⼒,严重情况下可能会导致数据库宕机的情况叫做缓存雪崩。
如果都不设置过期时间行不行;永久的;不会过期。这样子持久化的时候压力就会很大;刚开始RGB;刚开始有用信息可能存个10mb;全部都不过期;那么存个100mb。
解决方案:所以加锁排队执行(增加系统响应时间会牺牲一些用户体验);或者随机过期时间;再或者设置二级缓存;Redis失效就先去查二级缓存而不是直接查数据库
设置随机过期时间
// 缓存原本的失效时间
int exTime = 10 * 60;
// 随机数⽣成类
Random random = new Random();
// 缓存设置
jedis.setex(cacheKey, exTime+random.nextInt(1000) , value);
缓存穿透
缓存穿透是指查询数据库和缓存都⽆数据,因为数据库查询⽆数据,出于容错考虑,不会将结果保存到缓存中,因此每次请求都会去查询数据库,这种情况就叫做缓存穿透。也会给数据库造成很大压力。
就是你叫给我托管;但是你啥都没有。用户向我拿东西;发现什么都没有;就一直找数据库拿。数据库也是什么都没有。
解决方案:
空值缓存:当一个请求查询的结果在数据库中不存在时,可以将这个空结果也缓存起来,设置一个较短的过期时间。我们在缓存中存储一个表示空结果的占位值,并为这个占位值设置一个较短的过期时间,当请求到达时,即使缓存中没有有效的数据,也会返回这个空结果。由于过期时间较短,这个占位值会很快从缓存中移除。
缓存击穿
缓存击穿指的是某个热点缓存,在某⼀时刻恰好失效了,然后此时刚好有⼤量的并发请求,此时这些请求将会给数据库造成巨⼤的压⼒,这种情况就叫做缓存击穿。
解决方案:
加锁排队:
此处理⽅式和缓存雪崩加锁排队的⽅法类似,都是在查询数据库时加锁排队,缓冲操作请求以此来减少服务器的运⾏压⼒。
设置永不过期:
把热点的设置不过期;这样子就不会去请求数据库,但需要注意在数据更改之后,要及时更新此热点缓存,不然就会造成查询结果的误差。
缓存预热
系统启动的时候,先把查询结果预存到缓存中,以便⽤户后⾯查询时可以直接从缓存中读取,以节约⽤户的等待时间。
应用程序启动就先查询数据库然后同步到缓存中:
实现的三种思路:
1: 把需要缓存的⽅法写在系统初始化的⽅法中,这样系统在启动的时候就会⾃动的加载数据并缓存数据
2:把需要缓存的⽅法挂载到某个⻚⾯或后端接⼝上,⼿动触发缓存预热;
3:设置定时任务,定时⾃动进⾏缓存预热。