项目中的日常缓存

Springboot项目中,缓存的基本使用

缓存中间件

Redis

单线程的内存数据库

官网星标Java客户端

  • Jedis
    • Redis API的基本封装
    • 支持数据类型和Redis一致
  • Redission
    • Redis API的高级封装
    • 扩展了Redis支持的数据类型
    • 提供分布式操作
    • 基于Netty,线程安全
  • Lettuce
    • springboot默认的Redis客户端
    • 支持线程安全同步、异步、响应使用
    • 基于Netty,线程安全

KeyDB

基于Redis改造的多线程数据库,目前最快的NoSQL数据库

Java客户端

缓存机制

普通缓存

普通缓存.png

哨兵缓存

哨兵缓存.png

缓存的异常场景

缓存穿透击穿雪崩.png

缓存穿透

请求不存在的数据

场景:大量请求查询不存在的数据,请求会一路直达数据库。等于每次请求都要访问数据库,当数据库压力过大时有崩溃风险。

方案:

  • 增加请求合法性的校验,过滤无效请求。校验规则强依赖于业务,难以写成通用处理。
  • 某些请求key大量访问并且结果为空,对其可以加短时缓存,减小大量读库的压力。需要在写库时刷新缓存,不然会有数据不一致的情况。
  • 加缓存前先经过布隆过滤器,来判定是否存在该缓存

缓存击穿

请求数据存在,几个缓存失效

场景:请求数据存在,缓存失效时,大量请求直接访问数据库,当数据库压力过大时有崩溃风险。

方案:

  • 延长热点数据的失效时间,甚至可以永不过期(ttl=-1或异步刷新),看业务需要。
  • 刷新缓存时用互斥锁(Redis的setNX)来过滤数据库访问。结束时正常和异常情况都要释放锁,以便其他线程访问。

缓存雪崩

请求数据存在,大量缓存失效

场景:大量数据缓存同时失效,请求直达数据库,当数据库压力过大时有崩溃风险。

方案:

  • 延长热点数据的失效时间,甚至可以永不过期(ttl=-1或异步刷新),看业务需要。
  • 如果用的redis集群作为缓存,可将热点数据分布在不同节点上,来避免节点宕机引起的大量缓存失效。
  • 均匀TTL,避免大量缓存在同一时间点过期。
  • 采用双缓存/分级缓存,A为主要缓存,B为备用缓存,B的TTL可以在A的基础上延长。当数据在A中没有时,取B中数据,减缓缓存失效的频率。