第六届字节跳动青训营缓存学习记录| 青训营

115 阅读3分钟

Redis的三种缓存读写(更新)策略

旁路缓存

的时候:1.先到redis中读取 2.如果没有数据,就去数据库中读并返回 3. 再把数据放到redis中;

的时候:1.先更新数据库 2.然后直接删除缓存中对应的数据

如果先删除缓存,那么可能有大量的查询请求会达到数据库,并且修改缓存,可能将缓存的值修改回原来的旧值,造成mysql和redis数据不一致;

旁路缓存适合读多写少的情况。

这个逻辑要java自己写代码实现。

读写穿透

读的时候:1.先到redis中读取 2.如果没有数据,就去数据库加载数据到redis 3.redis返回数据

写的时候:1.先查cache,cache不存在,直接更新db;2.如果查到cache,直接更新cache,然后由redis更新db;

由redis去更新数据库,可能增加redis负担;

并且分布式redis可能没有这个功能。

异步缓存写入

与读写穿透相似,都是由redis来更新db,但是这个更新是批量异步更新的。这点和mysql的批量同步机制类似。

除了缓存Redis还能干什么

  1. 消息队列
  2. 分布式锁
  3. 限流

Redis事务

redis事务比较鸡肋,应用较少,不能保证原子性;且事务中的每个命令都要redis服务器进行一次交互,比较浪费网络资源。

为了解决redis事务的缺陷,提出了Lua脚本,可以批量的原子性的执行redis命令,减少网络开销。

Lua脚本在执行过程中不会有其他Lua脚本和redis执行同时执行;但是Lua脚本如果执行到一半出现崩溃,后面的不会执行,执行过的也不会回滚。

Redis生产问题

缓存穿透

频繁的使用大量不存在的key进行查询,导致缓存无法命中,给数据造成很大压力。

解决方案:

  1. 缓存无效的key【没太大用,因为黑客攻击会使用大量不同的key】
  2. 对客户端限流,限制请求频率。
  3. 布隆过滤器【将所有可能存在的请求的值都放在布隆过滤器中,请求来了之后先用布隆过滤器判断,如果请求无效,直接返回错误参数给客户端。】

缓存击穿

热点key的过期问题。热key过期瞬间会有大量请求打到数据库,给数据库造成压力。

解决方案:

  1. 设置热key永不过期,或设置一个比较长的过期时间。
  2. 在秒杀场景下,对热key提前预热,设置在秒杀结束之前不过期。
  3. 请求数据库写到缓存的这个操作,加互斥锁,保证只有一个请求到达数据库。

缓存雪崩

在同一时间有大量key同时失效,导致大量请求都打到数据库上。

解决方法:

  1. 失效时间都加一个随机值;
  2. 集群部署redis
  3. 设置所有Key永不过期【笨方法】

过期数据的删除策略

惰性删除

在用到key的时候,再对数据进行过期检查,删除过期数据,这样对CPU友好

定期删除

每隔一段时间对过期数据进行删除,这样对内存友好;

redis采用 惰性删除 + 定期删除的策略