缓存

使用多级缓存,减少访问redis。

  1. 使用 Caffeine,guava 作为一级本地缓存
  2. redis作为二级缓存

关键点💡

  1. 通过缓存空值来解决缓存穿透问题、通过异步加载缓存的方式来解决缓存击穿和雪崩问题
  2. 每个服务的一级缓存一致性,如果清空?
  3. 推模式: 大部分开源,使用reids的redis-订阅发布,进行广播要更新/删除的key。也可以使用rocektmq、rabbtmq等。, 基于zooKeeper进行,设置key的更新版本号,其它服务监听数据变化,如果有变化,则更新缓存。
  4. 拉模式: 使用redis-list和记录消费消息的偏移量来实现的。
  5. redis的value,可以使用序列化器并使用压缩算法

开源选型

1.2.1 JetCache(阿里)

(1)简介

JetCache是一个基于Java的缓存系统封装,提供统一的API和注解来简化缓存的使用。 JetCache提供了比SpringCache更加强大的注解,可以原生的支持TTL、两级缓存、分布式自动刷新,还提供了Cache接口用于手工缓存操作。

(2)特性

  • 支持注解
  • 支持自动刷新(除非设置一直刷新,不然的话一段时间没访问后就不刷新了,然后突然又有大流量那怎么应对呢:Jetcache设置了分布式锁,当缓存过期后,避免全部进到数据库层)
  • 支持本地缓存Caffeine(本地缓存支持Caffeine、Guava,如果仅支持HashMap或者Memcache的话,就需要斟酌了)
  • 不支持模糊删除,只支持KV键存储,不支持HashMap方式存储(我所知的基本上所有人用缓存都是KV键存储,很少用HashMap存储,但是KV键存储的话基本上避免不了模糊删除,而HashMap存书的话主要删除一个键即可,模糊删除如果使用keys的话,会全量扫阻塞其它线程,而且数据量巨大的话,返回的数组能直接裂开。如果使用游标方式,虽然不会太阻塞其它现成,但是数组还是能直接裂开,数组裂开的可能性应该比较小)
  • 不支持Redis集群访问(代码上获取Redis连接方式为单机方式,不是集群方式)

1.2.2 AutoLoadCache

(1)特性

  • 支持注解
  • 支持自动刷新
  • 支持本地缓存HashMap,不支持Caffeine、Guava方式
  • 支持HashMap方式存储,不支持模糊删除(不推荐模糊删除,以HashMap的方式存储是为了方便删除)
  • 支持Redis集群访问

1.2.3 LayeringCache

(1)简介

layering-cache是一个支持分布式环境的多级缓存框架,使用方式和spring-cache类似。使用Caffeine作为一级本地缓存,使用redis作为二级集中式缓存。一级缓存和二级缓存的数据一致性是通过推和拉两种模式相结合的方式来实现的。推主要是基于redis的pub/sub机制,拉主要是基于消息队列和记录消费消息的偏移量来实现的。

(2)特性

  • 支持注解
  • 支持自动刷新,不支持自定义刷新频率
  • 支持本地缓存Caffeine
  • 支持模糊删除(游标方式删除)
  • 支持Redis集群访问

1.2.4 J2Cache

(1)简介

J2Cache 是 OSChina 目前正在使用的两级缓存框架(要求至少 Java 8)。第一级缓存使用内存(同时支持 Ehcache 2.x、Ehcache 3.x 和 Caffeine),第二级缓存使用 Redis(推荐)/Memcached 。 由于大量的缓存读取会导致 L2 的网络成为整个系统的瓶颈,因此 L1 的目标是降低对 L2 的读取次数。 该缓存框架主要用于集群环境中。单机也可使用,用于避免应用重启导致的缓存冷启动后对后端业务的冲击。

(2)特性

  • 支持注解(Spring Aop原生注解)
  • 支持自动刷新,不能自定义刷新频率(Redis键过期时触发回调,需要Redis版本和手动配置,默认是关闭的;Redis、RabbitMq、RocketMq等消息方式通知本地缓存的更新)
  • 支持本地缓存Caffeine、Ehcache
  • 支持HashMap方式存储
  • 支持模糊删除(游标方式)
  • 支持Redis集群访问

1.2.5 Spring Aop注解

(1)特性

  • 支持注解

缓存设计要点

使用方式

大部分开源产品,都支持 注解 和 Template方式调用

缓存清除

  1. 使用ttl,到期后自动删除。
  2. 使用注解,显示删除。
  3. 发送mq消息处理
    1. 当做修改、删除时,发送消息MQ,由客户端消费消息进行缓存删除。使用mq方式,进行删除
    2. 监听binlog,进行删除mq

mq广播方案

如上,我们通过发送mq,进行缓存删除。那如何广播到每个服务器,进行删除本地缓存呢?

  1. 广播消息(注意要点,避免广播风暴)有开源实现
    1. 直接使用redis的,pub/sub 进行消息订阅。也可以参考LayeringCache,多存储一份消息到redis-list中。通过消费点位进行重置。
    2. rocketMq、RabbitMq等进行广播
  2. 新增缓存的版本号,通过zooKeeper每个服务器,监听缓存的版本。如果缓存版本号不一致,则进行删除、更新缓存。无开源实现

监控

  1. 缓存请求数、缓存命中数统计
  2. 监控热点数据

缓存击穿的方案

  1. 快过期数据异步加载
  2. 加载数据时,加 分布式锁
  3. 新增限流器,如使用guava的ratelimiter

资料

盘古开发框架 分布式多级缓存基于layering-cache
选型对比