缓存系统组成
- 缓存存储区:就是高速内存中的一种数据结构,用来提供数据存储和查找(可理解为hashmap);
- 缓存管理策略:缓存淘汰策略和缓存更新策略;
缓存淘汰策略
动态策略
动态策略的缓存数据完全来源于在线用户的请求,对缓存项保留一个权重值,权重值会根据查询命中情况动态调整,当缓存满时,优先淘汰权重值最低的缓存项。 LRU策略(最近最少使用策略)就是最常见的动态策略。
静态策略
事先通过离线计算出最热的top N,将这部分查询频率最高的内容,静态地缓存到系统里,这部分最热的数据不需要被淘汰,根据缓存容量大小,放入合适的缓存数据项。
动态静态混合策略
将前面两种策略结合一起使用。
缓存更新策略
如果数据源数据发生了更新,必须要将这个更新同步到缓存系统,否则就会出现缓存数据与数据源数据不一致的问题。
主动更新
对于数据一致性要求比较高的系统,希望数据源数据更新后,缓存数据也要立即更新。通常的做法是:系统监听数据源的变更消息,收到变更消息后,马上通知缓存系统系统更新数据。
被动失效
为每个缓存项,设置一个合理的失效时间,当到达失效时间后,缓存系统会自动失效掉这个缓存项; 那么对于一致性不是要求很高的场景,可以采用被动失效方案
缓存系统性能指标
- 缓存命中率
- 缓存内容与数据源数据的数据一致性
缓存分类
本地缓存
就是应用和缓存都部署在同一个进程里。
对于Java应用而言,本地缓存分为:
Java堆内本地缓存
缓存项存储在Java堆内内存里,可以直接存储Java的任何对象。最典型的Java堆内缓存框架就是Google的Guava Cache。
Java堆外本地缓存
缓存项存储在Java的堆外内存里,只能存储已经序列化了的对象。典型的Java堆外本地缓存框架就是Cassandra的OHC。
优点
- 没有网络开销,快速;
- 如果是Java的堆内本地缓存,可以直接缓存Java对象,没有序列化与反序列化开销。
缺点
- 内存空间有限,不能分配太大的空间;如果缓存体量很大,就不适合本地缓存了。
- 如果是Java堆内本地缓存,会增加GC的开销。
- 如果本地缓存集群规模比较大,缓存更新时,需要要通知到集群中的每个节点,如何保证集群中每个节点都通知到了,更新成本比较高。
- Java堆外本地缓存,会有序列化与反序列化开销
分布式缓存
分布式缓存将缓存系统设计成一个真正支持水平扩展的分布式系统,不像本地缓存会受到内存空间的限制,真正做到了水平伸缩;
典型的的分布式缓存系统有:Redis、Memcached等等