目录
缓存模型和思路
缓存更新策略
数据库和缓存不一致
缓存与数据库双写一致
缓存穿透
缓存雪崩
缓存击穿
速度快,好用,内存的读写性能远高于磁盘,缓存可以大大降低用户访问并发量带来的服务器读写压力
缓存模型和思路
标准的操作方式就是查询数据库之前先查询缓存,如果缓存数据存在,则直接从缓存中返回,如果缓存数据不存在,再查询数据库,然后将数据存入redis
代码思路:如果缓存有,则直接返回,如果缓存不存在,则查询数据库,然后存入redis。
缓存更新策略
目的:为了节约内存
内存淘汰:redis自动进行,当redis内存达到咱们设定的max-memery的时候,会自动触发淘汰机制,淘汰掉一些不重要的数据(可以自己设置策略方式)
超时剔除:当我们给redis设置了过期时间ttl之后,redis会将超时的数据进行删除,方便咱们继续使用缓存
主动更新:我们可以手动调用方法把缓存删掉,通常用于解决缓存和数据库不一致问题
数据库和缓存不一致
数据库的数据发送变化,缓存没有同步,此时会有数据一致性问题存在
解决方案:
应当是先操作数据库,再删除缓存,原因在于,如果你选择第一种方案,在两个线程并发来访问时,假设线程1先来,他先把缓存删了,此时线程2过来,他查询缓存数据并不存在,此时他写入缓存,当他写入缓存后,线程1再执行更新动作时,实际上写入的就是旧的数据,新的数据被旧数据覆盖了。
1.先删除缓存,再操作数据库时:更新数据库的时间较长,介入其他线程的概率很打
2.先操作数据库,再删除缓存时:写缓存的速度很快,介入其他线程的概率很小
缓存与数据库双写一致
如果缓存未命中,则查询数据库,将数据库结果写入缓存,并设置超时时间;采用删除策略,来解决双写问题,修改数据时,先修改数据库,再删除缓存(例如:根据id修改数据时)
当我们修改了数据之后,然后把缓存中的数据进行删除,查询时发现缓存中没有数据,则会从mysql中加载最新的数据,从而避免数据库和缓存不一致的问题
缓存穿透
缓存穿透 :缓存穿透是指客户端请求的数据在缓存中和数据库中
都不存在
,这样缓存永远不会生效,这些请求都会访问数据库
。
解决方案:(访问这个不存在的数据,那么在redis中也能找到这个数据就不会进入到数据库了)
缓存空对象 实现简单,维护方便(额外的内存消耗,可能造成短期的不一致)
布隆过滤 内存占用较少,没有多余key (实现复杂,哈希思想,存在哈希冲突,有误判可能)
主动防止:
增强id的复杂度,避免被猜测id规律
做好数据的基础格式校验
加强用户权限校验
做好热点参数的限流
缓存雪崩
缓存雪崩是指在同一时段大量的缓存key同时失效或者Redis服务宕机,导致大量请求到达数据库,带来巨大压力。
解决方案:
-
给不同的Key的TTL添加随机值
-
利用Redis集群提高服务的可用性
-
给缓存业务添加降级限流策略
-
给业务添加多级缓存
缓存击穿
缓存击穿问题也叫热点Key问题,就是一个被高并发访问并且缓存重建业务较复杂的key过期突然失效了,很多的请求访问会在瞬间给数据库带来巨大的冲击。
线程A在查询数据库并重新加载到缓存的
期间
,有大量的
其它线程来访问这些数据,缓存中没有,去数据库中找,导致数据库访问压力过大
常见的解决方案有两种:
-
互斥锁
大量同时访问这些数据时,只能有线程A去访问数据库,在访问时加上锁,其它线程获取锁失败,处于循环等待中,直到线程A访问数据库完毕,写入了缓存,使得其它线程可以缓存命中了
互斥锁实现逻辑:
-
逻辑过期
出现这个缓存击穿问题,主要原因是在于我们对key设置了过期时间,逻辑过期是不设置过期时间,而是把过期时间设置在 redis 的value中,后续通过逻辑去处理
在线程A,发现逻辑时间过期,获取有锁成功,会另开一个线程去完成查询数据重建缓存,线程A返回旧数据;当其它线程来时,发现获取锁失败会直接返回旧数据,直到另开的线程锁释放后才能得到新数据
逻辑过期实现逻辑:
对比:
模拟高并发:JMeter
下载安装:Jmeter安装教程【5.5】【Windows】jmeter详细安装配置教程,装不好你打我-CSDN博客