如何优化应用程序性能的内存缓存解决方案-Java缓存技术

本文探讨了各种Java缓存技术的提供,这些技术在改善应用程序性能方面发挥着至关重要的作用,并涵盖了各种场景。

几十年来,信息技术一直在极大地改善业务流程,并成为全球企业的战略解决方案。曾经被视为“可有可无”的东西现在已经成为必备之物。应用程序是任何业务的核心,在近年来,它们的使用量大幅增加。因此,响应时间变得更加重要。数据检索时间在用户体验中起着关键作用,并且在几乎所有商业应用程序中都是一个关键要求。如今有许多影响响应时间的因素,包括网络管道、协议、硬件、软件和互联网速度。庞大的IT基础设施和对系统性能的不断追求严重破坏了任何组织的战略目标。

本文旨在介绍一种Java缓存机制,以改善应用程序的性能。

缓存概念

缓存是用于临时存储频繁访问的数据的内存缓冲区。它通过避免从原始来源再次检索数据来提高性能。实际上,缓存是计算机/网络行业的一个已经应用了相当长时间的概念,因此根据使用情况有不同的缓存实现方式。事实上,路由器、交换机和个人电脑等设备都使用缓存来加速内存访问。另一个非常常见的缓存是在几乎所有个人电脑上使用的Web浏览器缓存,用于存储请求的对象,以避免多次检索相同的数据。在分布式JEE应用程序中,客户端/服务器端缓存在改善应用程序性能方面起着重要作用。客户端缓存用于临时存储通过网络从服务器传输的静态数据,以避免不必要地向服务器发出调用。另一方面,服务器端缓存用于存储从其他资源获取的数据。

缓存可以设计为单个/多个JVM或集群环境。以下是可使用缓存满足非功能性要求的不同可扩展性场景。

纵向扩展

可以通过升级单台机器的资源(CPU、RAM、HDD和SSD)并实施缓存来实现。但是,在将缓存升级到一定限制上存在一些局限性。在下面的用例中,可以通过增加内存并在应用程序级别实施缓存来提高应用程序的性能。

纵向扩展示意图

横向扩展

可以通过添加更多的机器并在每台机器上实施应用程序级别的缓存来实现。但是,在与下游应用程序通信方面仍然存在一些限制,无法添加额外的服务器。在下面的用例中,可以通过为每个应用程序添加一个服务器/缓存来提高整体应用程序的性能。数据库在满足此要求方面存在一些限制,但可以通过将静态/主数据存储在缓存中来减轻这种限制。

横向扩展-示意图

进程内缓存

进程内缓存使对象能够存储在与应用程序相同的实例中,即缓存在本地对应用程序可用,并共享相同的内存空间。

以下是考虑进程内缓存时的一些重要事项:

  1. 如果应用程序仅部署在一个节点上,即只有一个实例,则进程内缓存是正确的选择,可以存储频繁访问的数据并实现快速数据访问。

  2. 如果进程内缓存将在应用程序的多个实例中部署,则在所有实例之间保持数据同步可能是一个挑战,并可能导致数据不一致。

  3. 如果服务器配置有限,则这种类型的缓存可能会降低任何应用程序的性能,因为它共享相同的内存和CPU。垃圾收集器经常被调用来清理可能导致性能开销的对象。如果数据驱逐没有有效管理,可能会发生内存溢出错误。

进程内缓存示意图

内存分布式缓存

分布式缓存(键/值对象)可以在应用程序外部构建,支持对数据存储库的读写操作,在RAM中保存频繁访问的数据,并避免不断从数据源获取数据。这样的缓存可以部署在由多个节点组成的集群上,形成一个单一的逻辑视图。缓存客户端使用哈希算法来确定集群节点中对象的位置。

以下是考虑分布式缓存时的一些重要事项:

  1. 对于在关键性能环境下具有多个实例的集群中的中大型应用程序,内存分布式缓存是最佳选择。数据不一致性和共享内存不再是问题,因为分布式缓存以单一逻辑状态的形式部署在集群中。

  2. 由于需要通过网络访问缓存,跨进程的开销包括延迟、故障以及对象序列化等,可能会降低性能。

  3. 与进程内缓存相比,其实现更加困难。

内存分布式缓存示意图

内存数据库

这种类型的数据库也被称为主存数据库。它将数据存储在RAM中,而不是硬盘上,以实现更快的响应。数据以压缩格式存储,并具有良好的SQL支持。可以使用相关的数据库驱动程序来替代现有的关系数据库管理系统(RDBMS)。

通过用内存数据库替换RDBMS,可以提高应用程序的性能,而无需更改应用程序层。只能进行纵向扩展以扩大内存数据库的规模。

内存数据网格

这种分布式缓存解决方案可以快速访问频繁使用的数据。数据可以在多个节点上进行缓存、复制和分区。

实施内存数据网格将提高应用程序的性能并扩展其规模,而无需更改关系数据库管理系统(RDBMS)。

关键特点包括:

  • 在内存中对数据进行并行计算

  • 在内存中进行搜索、聚合和排序

  • 在内存中进行事务管理

  • 事件处理

缓存的使用场景

有一些使用场景可以通过各种商业/开源缓存框架来提高应用程序性能,并且可以在任何企业应用程序中进行配置。以下是常见的缓存使用场景。

应用程序缓存

应用程序缓存是应用程序使用的本地缓存,用于将频繁访问的数据保留在内存中。应用程序缓存会自动驱逐条目以维护其内存占用。

应用缓存流程图

Level 1 (L1) Cache

这是每个会话的默认事务性缓存。它可以由任何Java持久化框架(JPA)或对象关系映射(ORM)工具进行管理。

L1缓存存储属于特定会话的实体对象,并在会话关闭后被清除。如果在一个会话中有多个事务,所有实体将来自这些事务。

Level 2 (L2) Cache

L2缓存可以配置为提供自定义缓存,用于保存所有需要缓存的实体数据,包括属性、关联和集合。它在会话工厂级别进行配置,并在会话工厂可用时存在。

L2缓存可以配置为在以下范围内使用:

  • 应用程序中的会话。

  • 具有相同数据库的相同服务器上的应用程序。

  • 同一数据库上不同服务器上的不同应用程序的集群。

如果配置了L2缓存,则可以使用L1/L2缓存的方式:

  • 标准的ORM框架首先在L1缓存中查找实体,然后再在L2缓存中查找。L1缓存是查找实体的初始搜索空间。如果找到实体的缓存副本,则返回该实体。

  • 如果在L1缓存中找不到缓存的实体,则会在L2缓存中进行查找。

  • 如果在L2缓存中找到缓存的实体,则将其存储在L1缓存中,然后返回。

  • 如果实体既不在L1缓存中也不在L2缓存中,则从数据库中获取该实体,并在返回给调用方之前将其存储在两个缓存中。

  • 当任何会话对实体进行修改时,L2缓存会进行验证/刷新。

  • 如果数据库被外部进程修改,即没有应用程序会话参与,那么除非通过框架API或自定义API实现某种缓存刷新策略,否则无法隐式刷新L2缓存。

以下通信图说明了使用L1/L2缓存的情况:

使用L1/L2缓存的通信图

混合缓存

混合缓存是标准ORM框架提供的缓存与开源/自定义/JDBC API实现的缓存的结合。应用程序可以使用混合缓存来利用仅限于标准ORM框架的缓存功能。这种类型的缓存通常在响应时间至关重要的关键任务应用程序中使用。

混合缓存流程图

缓存设计考虑因素

缓存设计时需要考虑数据加载/更新、性能/内存大小、逐出策略、并发性和缓存统计等因素。

数据加载/更新

将数据加载到缓存中是一个重要的设计决策,以保持所有缓存内容的一致性。可以考虑以下方法来加载数据:

  • 使用标准ORM框架(如Hibernate或OpenJPA)提供的默认函数/配置。

  • 使用开源缓存API(如Google Guava)或COTS产品(如Coherence、Ehcache或Hazelcast)实现键值映射。

  • 通过自动或显式插入编程方式加载实体。

  • 通过同步或异步通信进行外部应用程序加载。

性能/内存大小 32/64位

可用内存是实现性能SLA的重要因素,它取决于32/64位JRE,而后者又依赖于32/64位CPU架构的机器。在32位系统/JRE中,约有1.5 GB的堆留给应用程序使用,而在64位系统/JRE中,堆大小取决于RAM大小。

内存的高可用性会增加运行时的成本,并可能产生负面影响。

  • 与32位相比,64位需要30-50%更多的堆空间,因为内存布局不同。

  • 维护更大的堆空间需要更多的GC工作来清理未使用的对象,可能会降低性能。可以通过调整GC进行微调以限制GC暂停时间。

逐出策略

逐出策略使缓存能够确保缓存的大小不超过最大限制。根据逐出策略,会从缓存中删除现有元素,但可以根据应用程序要求进行定制。常用的缓存逐出算法有:

  • 最近最少使用(LRU)

  • 最不经常使用(LFU)

  • 先进先出(FIFO)

并发性

并发性是企业应用程序中常见的问题。它会导致冲突并使系统处于不一致状态。当多个客户端在缓存刷新期间同时尝试更新相同的数据对象时,就会发生并发性问题。常见的解决方案是使用锁定机制,但这可能会影响性能。因此,应考虑优化技术。

缓存统计

缓存统计信息有助于了解缓存的健康状况,并提供有关缓存行为和性能的信息。通常,可以使用以下属性来进行缓存统计:

  • 命中计数:找到对象时遇到的查找次数

  • 未命中计数:未找到对象时遇到的查找次数

  • 成功加载计数:成功加载条目的数量

  • 总加载时间:加载元素所用的总时间

  • 加载异常计数:加载条目时抛出的异常数量

  • 逐出计数:从缓存中逐出的条目数

概述:各种缓存解决方案

Java有多种可用的缓存解决方案 - 找到适合您的用例的正确选择取决于您的需求。以下是一些问题和比较,可帮助确定最具成本效益且可行的缓存解决方案:

  • 您需要一个轻量级还是完整的缓存解决方案?

  • 您需要一个开源、商业还是框架提供的缓存解决方案?

  • 您需要进程内还是分布式缓存?

  • 一致性和延迟需求之间的权衡如何?

  • 您是否需要维护事务性/主数据的缓存?

  • 您是否需要复制缓存?

  • 关于性能、可靠性、可扩展性和可用性方面有什么要考虑的?

根据这些问题和比较,您可以确定最适合您需求的成本效益和可行性的缓存解决方案。

缓存解决方案缓存类型开源复制(JSR-107)兼容配置复杂性逐出算法集群支持
EhcacheLevel 2级别简单LRU, LFU
HazelcastLevel 2级别简单LRU, LFU
Redis/Memcached分布式中等LRU
Google Guava进程内-简单LRU
Coherence分布式复杂LRU, LFU, 混合, 自定义

请注意,复制缓存意味着缓存可以在集群中多个节点之间维护相同的数据副本。这有助于实现高可用性和容错性。

(JSR-107)兼容表示符合Java Caching API标准,该标准提供了一组用于在Java中进行缓存的公共接口和功能。

配置复杂性指的是配置和设置缓存解决方案的难易程度。

逐出算法确定在缓存达到最大大小时从中删除哪些元素。LRU表示最近最少使用,FLU表示最不经常使用,LFU表示最频繁使用率最低。

集群支持表示缓存解决方案是否支持集群,并能够将数据分布在集群中的多个节点之间。

根据这些因素,您可以选择最适合您特定需求的缓存解决方案。

关键词:Java缓存技术,改善应用程序性能,性能优化,内存缓存文章来源地址https://www.toymoban.com/diary/system/636.html

到此这篇关于如何优化应用程序性能的内存缓存解决方案-Java缓存技术的文章就介绍到这了,更多相关内容可以在右上角搜索或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

原文地址:https://www.toymoban.com/diary/system/636.html

如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请联系站长进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用
上一篇 2023年12月28日 14:55
下一篇 2023年12月29日 15:41

相关文章

  • 如何调试移动应用程序数据库问题并优化数据存储性能

    在移动应用开发的动态领域中,无缺陷的用户体验是最终目标。然而,在表面下隐藏着一个复杂的数据存储和检索网络。当数据库问题出现时,它们可能会干扰甚至最精心设计的应用程序。这就是为什么了解如何调试移动应用程序数据库问题和优化数据存储性能对于追求卓越

    2024年02月13日
    浏览(53)
  • 优化您的Spring应用程序:缓存注解的精要指南

    当我们构建和运行Spring应用程序时,通常面临一个共同的挑战:性能。无论是为了提供更快的响应时间、更高的并发处理能力,还是为了降低数据库或外部服务的负载,性能优化一直是开发人员和系统管理员的关注焦点。 在本篇博客中,我们将深入研究Spring的 @Cacheable 、 @

    2024年02月07日
    浏览(54)
  • Linux内存从0到1学习笔记(6.12 应用程序是如何申请内存的呢?)

        前面提到了应用程序大多基于glibc的malloc/free进行内存的分配。这里不讨论共享内存,因为共享内存都是预先分配好的,所以由共享内存mmap和shm所设计的内存泄漏比较少见。     接下来我们从应用调用的维度来看下,应用程序都有哪些调用入口,以及它们是如何申请和释

    2024年02月03日
    浏览(64)
  • 小程序如何修改缓存中的某一个字段的值;小程序中如何应用vant组件 如:van-dropdown-item、van-field

    将数据放入指定缓存中。 这里缓存块的名称叫‘mydata’,你可以根据自己的需求,取合适的名字。代码如下 效果:这里是存了个对象当示例。也可以存数组,字符串等。 使用 wx.getStorageSync(‘myData’),即可取出‘myData’中缓存的数据。以下代码打印结果为 hello 先取出数据,

    2024年02月09日
    浏览(61)
  • JavaScript中的数据缓存与内存泄露:解密前端性能优化与代码健康

    ​🌈个人主页:前端青山 🔥系列专栏:JavaScript篇 🔖 人终将被年少不可得之物困其一生 依旧 青山 ,本期给大家带来JavaScript篇专栏内容:JavaScript-数据缓存与内存泄露 目录 说说你对事件循环的理解 一、是什么 二、宏任务与微任务 微任务 宏任务 三、async与await async await 四、

    2024年02月03日
    浏览(76)
  • 极速Python编程:利用缓存加速你的应用程序

    在软件开发中,缓存是一种常用的技术,用于提高系统性能和响应速度。Python提供了多种缓存技术和库,使我们能够轻松地实现缓存功能。本文将带您从入门到精通,逐步介绍Python中的缓存使用方法,并提供实例演示。 缓存基础知识 什么是缓存 缓存的工作原理 缓存的优势和

    2024年02月16日
    浏览(48)
  • 【温故而知新】HTML5 应用程序缓存

    HTML5是HTML的最新版本,它引入了许多新的元素和功能,以适应现代网页开发的需求。以下是HTML5的一些主要特点: 新增语义元素 :HTML5引入了许多新的语义元素,如 header、footer、article、section 等,这些元素有助于提高网页的结构化和可访问性。 媒体支持 :HTML5引入了 audio 和

    2024年01月23日
    浏览(74)
  • 查看ios 应用程序性能

    目录 摘要 前言 性能概括 CPU内存监控 内存监控 磁盘监控 网络监控 GPU fps 本篇博文将介绍一款重量级性能测试工具——克魔助手,针对iOS应用程序的性能监控进行详细介绍。通过克魔助手,开发者可以方便地查看应用程序的CPU、内存、GPU性能情况,以及网络监控和抓包等功能

    2024年02月03日
    浏览(59)
  • 轻松搞定Spring集成缓存,让你的应用程序飞起来!

    主页传送门:📀 传送   Spring 提供了对缓存的支持,允许你将数据存储在缓存中以提高应用程序的性能。Spring 缓存抽象基于 Java Caching API,但提供了更简单的编程模型和更高级的功能。   Spring 集成缓存提供了一种方便的方式来使用缓存,从而提高应用程序的性能。Spr

    2024年02月07日
    浏览(62)
  • windows应用程序icon缓存、查看图标、icon制作方法

    在vs中替换c++程序的图标后,需要重新编译,但是很多情况下都不会刷新,还是看到老的图标,只能重启电脑才能看到新的图标。 通过ChatGPT得到相关的回答如下: 如果在 Windows 上更换了可执行文件 (.exe) 的图标,但是在图标文件已经更改的情况下仍然显示旧的图标,可能是因

    2024年02月14日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包