任何技术,无论它有多先进,都无法解决您的问题,如果你实施不当。缓存,正是当涉及到使用分布式缓存时,只能通过正确使用和配置来加速应用程序。从这个角度看,Apache Ignite 也不例外,在生产环境中使用它之前,需要考虑几个步骤。

在本文中,我们描述了各种技术,可以帮助您规划和充分使用 Apache Ignite。

  1. 在使用点火群集之前,应进行适当的容量规划。执行文书工作以了解缓存的大小、CPU的数量或需要多少 JVM。假设您在 10 个应用程序服务器中使用 Hibernate 作为 ORM,并希望将 Ignite 用作 L2 缓存。计算维护 SLA 所需的总内存使用量和 Ignite 节点数。不正确的 Ignite 节点数可能成为整个应用程序的瓶颈。请使用 Apache Ignite官方文档准备系统容量规划。

  2. 选择最佳部署选项。您可以将 Ignite 用作嵌入式或实际群集拓扑。它们都包含一些优点和缺点。当 Ignite 与应用程序在同一 JVM(嵌入式模式下)运行时,从缓存获取数据的网络往返行程是最少的。但是,在这种情况下,Ignite 使用相同的 JVM 资源以及应用程序,这可能会影响应用程序的性能。此外,在嵌入式模式下,如果应用程序死,Ignite 节点也会失败。另一方面,当 Ignite 节点在单独的 JVM 上运行时,从群集获取数据的网络开销最小。因此,如果您有内存占用量较小的 Web 应用程序,则可以考虑在同一 JVM 中使用 Ignite 节点。

  3. 使用堆上缓存获得最佳性能。默认情况下,Ignite 使用 Java 堆外存储缓存条目。使用堆外存储数据时,数据去序列化总是有一定的开销。为了缓解延迟并获得最大的性能,可以使用堆上缓存。您还应考虑到 Java 堆大小几乎有限,并且每当使用堆上缓存时,都会存在 GC(垃圾回收)开销。因此,每当使用少量的缓存时,请考虑使用堆上缓存,并且缓存条目几乎是常量。

  4. 尽可能使用原子缓存模式。如果不需要强的数据一致性,请考虑使用原子模式。在原子模式下,每个 DML 操作要么成功,要么失败,读取和写入操作都不会锁定数据。此模式提供比事务模式更好的性能

<property name="cacheConfiguration">
    <list>
        <bean class="org.apache.ignite.configuration.CacheConfiguration">
            <property name="name" value="testCache" />
            <property name="atomicityMode" value="ATOMIC" />
        </bean>
    </list>
</property>

5. 禁用不必要的内部事件通知。Ignite 具有丰富的事件系统,用于通知用户/节点有关各种事件,包括缓存修改、逐出、压缩、拓扑更改等。由于每秒生成数千个事件,因此会在系统上创建额外的负载。这可能导致性能显著下降。因此,强烈建议仅启用应用程序逻辑所需的那些事件。

<bean class="org.apache.ignite.configuration.IgniteConfiguration">
    <!-- Enable events that you need and leave others disabled -->
    <property name="includeEventTypes">
        <list>
            <util:constant static-field="org.apache.ignite.events.EventType.EVT_TASK_STARTED"/>
            <util:constant static-field="org.apache.ignite.events.EventType.EVT_TASK_FINISHED"/>
            <util:constant static-field="org.apache.ignite.events.EventType.EVT_TASK_FAILED"/>
        </list>
    </property>
</bean>

6. 关闭备份的副本。如果您使用的是分区缓存,并且数据丢失对您来说并不重要,请考虑禁用分区缓存的备份。启用备份后,Ignite 缓存引擎会维护每个条目的远程副本,这需要网络交换。要关闭备份的副本,请使用以下缓存配置:

<bean class="org.apache.ignite.configuration.IgniteConfiguration">
    <property name="cacheConfiguration">
        <bean class="org.apache.ignite.configuration.CacheConfiguration">
            <!-- Set cache mode. -->
            <property name="cacheMode" value="PARTITIONED"/>
            <!-- Set number of backups to 0-->
            <property name="backups" value="0"/>
        </bean>
    </property>
</bean>

7. 同步对同一密钥的请求。让我们用一个例子来解释。假设您的应用程序必须每秒处理 5000 个请求。其中大多数由一个密钥请求。所有线程都遵循以下逻辑:如果缓存中没有密钥的值,则查询到数据库。最后,每个线程都转到数据库,并将密钥的值更新到缓存中。因此,应用程序花费的时间比缓存根本不存在的时间要多。这是应用程序在每次使用缓存时速度减慢的常见原因之一。

但是,此问题的解决方案很简单:同步相同密钥的请求1、Apache Ignite 支持 @Cacheable  a具有同步属性的符号,以确保单个线程正在形成缓存值。为此,您必须添加 sync 如下属性:

@Cacheable(value = "exchangerate", sync = true)
public String getExchangerate(String region) {
}

8. 关闭或调谐耐用内存。自版本 2.1 以来,Apache Ignite 已拥有自己的持久性实现。不幸的是,持久性减慢了系统的速度。WAL 使系统速度更加慢。如果不需要数据持久性,可以禁用或关闭 WAL 存档。在 Apache Ignite 中,从版本 2.4 开始,可以禁用 WAL 而不重新启动整个群集,如下所示:

ALTER TABLE tableName NOLOGGING
ALTER TABLE tableName LOGGING

顺便说一下,您还可以根据您的要求调整 WAL 日志记录级别。默认情况下,WAL 日志级别在 DEFAULT 模式下启用,从而保证最高级别的数据持久性。您可以将日志更改为以下级别之一:

1. LOG_ONLY。
2. 背景。
3. 无。

缓存带来巨大的性能优势,节省了不必要的网络往返,并降低了 CPU 成本。许多人认为缓存是使一切更快、更凉爽的简单方法。然而,正如实践所表明的,缓存的不正确使用只会使事情变得更糟。缓存是仅在正确使用时才能提高性能的机制。因此,在项目中实现之前,请记住这一点,在所有相关案例之前和之后进行测量。

如果您有任何意见或想法,请不要犹豫。这篇文章的部分取自阿帕奇点燃书。如果它让你感兴趣,请查看本书的其余部分,以了解更多信息。

Comments are closed.