项目中的日常缓存
Springboot项目中,缓存的基本使用
缓存中间件
Redis
单线程的内存数据库
官网星标Java客户端
- Jedis
- Redis API的基本封装
- 支持数据类型和Redis一致
- Redission
- Redis API的高级封装
- 扩展了Redis支持的数据类型
- 提供分布式操作
- 基于Netty,线程安全
- Lettuce
- springboot默认的Redis客户端
- 支持线程安全同步、异步、响应使用
- 基于Netty,线程安全
KeyDB
基于Redis改造的多线程数据库,目前最快的NoSQL数据库
Java客户端
缓存机制
普通缓存
哨兵缓存
缓存的异常场景
缓存穿透
请求不存在的数据
场景:大量请求查询不存在的数据,请求会一路直达数据库。等于每次请求都要访问数据库,当数据库压力过大时有崩溃风险。
方案:
- 增加请求合法性的校验,过滤无效请求。校验规则强依赖于业务,难以写成通用处理。
- 某些请求key大量访问并且结果为空,对其可以加短时缓存,减小大量读库的压力。需要在写库时刷新缓存,不然会有数据不一致的情况。
- 加缓存前先经过布隆过滤器,来判定是否存在该缓存
缓存击穿
请求数据存在,几个缓存失效
场景:请求数据存在,缓存失效时,大量请求直接访问数据库,当数据库压力过大时有崩溃风险。
方案:
- 延长热点数据的失效时间,甚至可以永不过期(ttl=-1或异步刷新),看业务需要。
- 刷新缓存时用互斥锁(Redis的setNX)来过滤数据库访问。结束时正常和异常情况都要释放锁,以便其他线程访问。
缓存雪崩
请求数据存在,大量缓存失效
场景:大量数据缓存同时失效,请求直达数据库,当数据库压力过大时有崩溃风险。
方案:
- 延长热点数据的失效时间,甚至可以永不过期(ttl=-1或异步刷新),看业务需要。
- 如果用的redis集群作为缓存,可将热点数据分布在不同节点上,来避免节点宕机引起的大量缓存失效。
- 均匀TTL,避免大量缓存在同一时间点过期。
- 采用双缓存/分级缓存,A为主要缓存,B为备用缓存,B的TTL可以在A的基础上延长。当数据在A中没有时,取B中数据,减缓缓存失效的频率。