redis缓存

1.什么是缓存

缓存就是数据交换的缓冲区,称为cache,是存储数据的临时地方,一般读写性能较高

典型例子就是在计算机的CPU和内存、磁盘。CPU的运算能力非常强大,运算速度已经远远超过内存或者磁盘读写数据的能力。但是先读到数据才能进行处理,那么数据读写能力较低就限制了CPU的性能。CPU内部添加缓存之后,就直接从缓存中读取数据进行计算,充分应用了CPU的性能。

缓存的应用场景

redis缓存_第1张图片

缓存的作用

  • 降低后端负载
  • 提高读写效率,降低响应时间(可应对更高并发的场景了)

缓存的成本

  • 数据一致性成本(数据库数据更新了,缓存的数据还是旧数据,命中缓存就读到了旧数据,可能带来严重问题)
  • 解决问题需要进行代码维护,维护成本较高
  • 运维成本(集群模式的部署和维护、硬件成本)

 

添加redis缓存

redis缓存_第2张图片

2.缓存更新策略

针对 数据一致性 问题,提出了缓存更新策略,用来解决数据一致性问题、

更新策略主要分为三种

redis缓存_第3张图片

低一致性需求:使用内存淘汰机制

高一致性需求:使用主动更新,并以剔除超时时间兜底

主动更新策略:

Cache Aside Pattern:由缓存的调用者,在更新数据库时同时更新缓存
Read/Write Through Pattern:缓存与数据库整合为一个服务,由服务来维护一致性。调用者调用该服务,无需关心缓存一致性问题
Write Behind Caching Pattern:调用者只操作缓存,用其他线程异步将缓存持久化到数据库,保证最终一致

一般使用的主动更新策略是第一种,操作缓存和数据库时还需要注意三个问题

1.删除缓存还是更新缓存?
更新缓存:每次更新数据库都更新缓存,无效写操作较多
删除缓存:更新数据库时让缓存失效,查询时再更新缓存(有人访问才更新,延迟加载,写的频率更低,有效更新更多,适合选择的方案)

2.如何保证缓存与数据库的操作的同时成功或失败?保证操作原子性
单体系统,将缓存与数据库操作放在一个事务
分布式系统,利用TTC等分布式事务方案

3.先操作缓存还是先操作数据库

先操作缓存再操作数据库

正常情况

redis缓存_第4张图片

异常情况: 

redis缓存_第5张图片

 redis缓存_第6张图片

redis缓存_第7张图片

 删除缓存很快了,更新数据库相对较慢,查写操作也快,所以上述情况发生概率是不小的

再看先操作数据库,后删除缓存

正常情况

redis缓存_第8张图片

特殊情况:缓存失效

redis缓存_第9张图片

 

 redis缓存_第10张图片

场景:并发、缓存失效

1和4步骤是写缓存的操作,相比线程进行数据库的更新速度(写操作)来说,速度是极快的,因此这种情况不易发生(如果发生了,可以在加一个超时时间,超时后就删除了)

综上所述,这两种方案都有可能的发生线程不安全问题,但是方案二(先操作数据库,再删除缓存)更加安全

3.缓存穿透

redis缓存_第11张图片

请求到达redis为命中,然后请求到达数据库,也为命中。如果大量的不存在于数据库中的数据同时打到数据库,数据库很可能会难以承载而崩溃。

缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会生效,这些请求都打到数据库 

解决方案:

缓存null值

redis缓存_第12张图片 

优点:实现简单维护方便

缺点:额外的内存消耗(设置TTL )、可能造成短期不一致(假如数据库真的插入了对应数据,之前redis写入的缓存是null,就数据不一致了,TTL过期后才能正确查询)

布隆过滤

redis缓存_第13张图片

4.缓存雪崩

缓存雪崩是同一时段大量的缓存key同时失效或者Redis服务宕机,导致大量的请求到达数据库,带来巨大的压力

redis缓存_第14张图片

解决方案:

给不同的key的TTL添加随机值(控制过期时间)

利用redis集群提高服务的可用性(哨兵机制)

给缓存业务添加限流策略(拒绝服务,牺牲部分服务,保护数据库)

给业务添加多级缓存

5.缓存击穿

 缓存击穿问题也叫做热点key问题,就是一个被高并发访问的并且缓存重建业务较复杂的key突然失效了,无数的请求访问会瞬间非数据库带来巨大的冲击

缓存重建的时间比较长,后续的所有请求都会打到数据库上

redis缓存_第15张图片

解决方案:

互斥锁

只有获取锁成功的现线程才能重建,其它线程等待(保证了数据一致性)

redis缓存_第16张图片

其它线程都在等待,性能比较差 

逻辑过期

redis缓存_第17张图片

 发现数据过期后,获取锁,交由另一个线程进行重建。然后返回旧的过期数据,别的线程也是如此,在重建完成前都返回过期数据,在重建完成后返回最新的数据。所有的请求不会直接打到数据库上、不能保证数据的一致性

对比

redis缓存_第18张图片

 

你可能感兴趣的:(redis,java,开发语言,redis)