Skip to content

Latest commit

 

History

History

cache-practice

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

Java Cache Practice

👉 应用开发中,Cache毫无疑问是很重要的一块:提升应用性能的关键,降低像DB这样关键资源的负荷;但Cache的使用有很多要注意的问题与陷阱。

关于Cache的问题/陷阱

在应用开发通过Cache来性能优化时,要注意或了解下面的问题/陷阱:

  1. 多级 Cache支持
    • 应用开发时往往会考虑加上内存Cache,因为内存Cache性能高很多于Cache中间件(如Memcached
      • 当然要特别注意的是 内存Cache数据条目上限 的设置,避免内存消耗过多导致应用瘫痪。
      • 由于内存中Cache数据条目,如何决定哪些数据要Cache,移出策略的设置变得要好好思考。
      • 如果Cache涉及数据条目很多、很分散没有时间局部性,那么内存Cache可能是浪费内存且增加了操作性能更低。
    • 这样数据访问路径就成了:内存Cache -> 远程Cache -> 实际数据(如DB
  2. 无实际数据时的 防击穿
    导致没有数据时,一直会访问DB
    自己实现时,容易忽略这点
  3. Cache中没有数据时,即首次加载时,并发的Cache请求的 防击穿
    期望在这种情况下,并发请求只会触发一次实际数据请求,数据请求完成后,所有并发Cache请求都返回数据。
    自己实现时,容易忽略这点
  4. 使用Cache请求时,透明 数据的加载,即
    • 业务实现不需要自己写这样的逻辑:
      • 如果Cache中没有数据读实际数据,设置好Cache
      • 如果Cache中有数据返回Cache数据。
      • 这样逻辑繁琐易漏易错。
    • Cache会持有加载实际数据的Loader,参见GuavaCacheLoader模式

如果有『击穿』的情况,系统性能压力上来时会雪崩,而你想依赖的之前性能压测的性能数据已经没有意义了。

使用库 vs. 自己实现?

总得来说,应该使用Cache框架而不应该自己去实现:

  1. Cache要解决好的问题与业务无关很稳定,所以一定有好的Cache框架,并解决好上面这些问题。
  2. Cache的并发控制/线程安全的问题,对于一般应用开发者来说,可能没有概念,即使是面向自己场景的简单实现也可能漏洞百出。
  3. 完整的Cache实现以应对不同场景的需求,要考虑很多方面:
    1. 条目的逐出(Eviction)/过期策略,如
      • 最简单常用的基于固定数目上限的LRU
      • 基于时间的逐出
      • 基于引用,以加速内存GC
    2. 逐出条目的回调,方便应用可以集成条目的生命周期,如添加监控
    3. Cache的命中率,方便了解系统的情况
    4. ……

Java Cache Frameworks/Libs

Cache Middleware

相关资料