• 架构设计 - 本地热点缓存


    摘要:

    缓存体系架构:

    一级缓存:JVM本地缓存

    二级缓存:Redis集中缓存

    三级缓存:Nginx缓存(Proxy Cache缓存;Lua缓存)

    Java(或任何编程语言)中的本地热点缓存(通常指的是本地缓存,如使用Guava Cache、EhCache、Caffeine等库实现的缓存,或者简单的HashMap/ConcurrentHashMap作为缓存)在性能优化中起着至关重要的作用。以下是为什么Java(以及许多其他系统和应用)需要本地热点缓存的几个主要原因:

    减少数据库或远程服务调用

    • 当应用需要频繁访问数据库或远程服务来获取数据时,这些调用可能会成为性能瓶颈。本地缓存允许应用存储常用数据,并在需要时直接从缓存中获取,而不是每次都进行远程调用。

    降低网络延迟

    • 对于分布式系统,远程服务调用通常涉及网络延迟。本地缓存可以显著减少这些延迟,因为数据直接从本地内存中获取。

    提高响应速度

    • 由于数据是从本地内存中检索的(比从磁盘或网络获取要快得多),因此应用可以更快地响应请求。

    减轻数据库压力

    • 通过减少数据库查询,本地缓存可以帮助减轻数据库服务器的负载,使其能够更有效地处理其他请求。

    实现一致性策略

    • 本地缓存允许应用实现更复杂的一致性策略,如最终一致性,同时保持高性能。

    缓存热点数据

    • 在许多应用中,存在所谓的“热点数据”,即被频繁访问的数据。本地缓存可以确保这些热点数据始终在内存中,从而加速访问。

    支持事务和并发

    • 一些缓存库(如Guava Cache和Caffeine)提供了对事务和并发的支持,确保在多线程环境中缓存的正确性和性能。

    缓存失效和更新

    • 本地缓存通常具有失效策略(如基于时间或基于访问的失效)和更新策略(如写穿、写回或刷新),以确保缓存中的数据与数据源保持一致。

    减少资源消耗

    • 虽然缓存本身会消耗一些内存,但它通常可以显著减少CPU和网络资源的消耗,因为应用不需要频繁地进行远程调用或执行复杂的计算。

    易于实现和集成

    • Java提供了许多易于使用和集成的缓存库和框架,使得在应用中实现本地缓存变得相对简单。

    总之,本地热点缓存是优化Java应用性能的重要工具之一,它可以帮助应用更快地响应请求、减轻数据库压力、降低网络延迟,并提高整体系统的可扩展性和可靠性。

    基于 google guava 实现的本地热点缓存示例

    1. import com.google.common.cache.CacheBuilder;
    2. import com.google.common.cache.CacheLoader;
    3. import com.google.common.cache.LoadingCache;
    4. import java.time.Duration;
    5. import java.util.concurrent.Executors;
    6. /**
    7. * @desc 本地热点缓存 Cache 工具类
    8. *
    9. */
    10. public class CacheUtils {
    11. /**
    12. * 构建异步刷新的 LoadingCache 对象
    13. *
    14. * @param duration 过期时间
    15. * @param loader CacheLoader 对象
    16. * @return LoadingCache 对象
    17. */
    18. public static LoadingCache buildAsyncReloadingCache(Duration duration, CacheLoader loader) {
    19. return CacheBuilder.newBuilder()
    20. // 设置缓存窗口初始容量为10
    21. .initialCapacity(10)
    22. // 设置缓存中存储的KEY超过100个后按照LRU策略移除
    23. .maximumSize(100)
    24. // 只阻塞当前数据加载线程,其他线程返回旧值
    25. .refreshAfterWrite(duration)
    26. // 通过 asyncReloading 实现全异步加载,包括 refreshAfterWrite 被阻塞的加载线程
    27. .build(CacheLoader.asyncReloading(loader, Executors.newCachedThreadPool()));
    28. }
    29. /**
    30. * 构建同步刷新的 LoadingCache 对象
    31. *
    32. * @param duration 过期时间
    33. * @param loader CacheLoader 对象
    34. * @return LoadingCache 对象
    35. */
    36. public static LoadingCache buildCache(Duration duration, CacheLoader loader) {
    37. return CacheBuilder.newBuilder().refreshAfterWrite(duration).build(loader);
    38. }
    39. }

  • 相关阅读:
    寻找数组中最接近目标的数字
    面了个拿 30K 出来的测试,见识到了什么叫真正的测试天花板
    什么密码,永远无法被黑客攻破?
    AMQP协议详解
    软考高级之系统架构师系列之UP、RUP、4+1视图、JAD、JRP、RAD
    vue实现一个鼠标滑动预览视频封面组件(精灵图版本)
    JavaScript+css实现的计时器动画素材html页面前端源码
    【设计模式】Head First 设计模式——构建器模式 C++实现
    师德师风演讲稿写作格式:如何用三句话吸引听众的注意力
    PHP将数据集转换成树状结构
  • 原文地址:https://blog.csdn.net/suiusoar/article/details/139756176