任何技术,无论它有多先进,都无法解决您的问题,如果你实施不当。缓存,正是当涉及到使用分布式缓存时,只能通过正确使用和配置来加速应用程序。从这个角度看,Apache Ignite 也不例外,在生产环境中使用它之前,需要考虑几个步骤。
在本文中,我们描述了各种技术,可以帮助您规划和充分使用 Apache Ignite。
-
在使用点火群集之前,应进行适当的容量规划。执行文书工作以了解缓存的大小、CPU的数量或需要多少 JVM。假设您在 10 个应用程序服务器中使用 Hibernate 作为 ORM,并希望将 Ignite 用作 L2 缓存。计算维护 SLA 所需的总内存使用量和 Ignite 节点数。不正确的 Ignite 节点数可能成为整个应用程序的瓶颈。请使用 Apache Ignite官方文档准备系统容量规划。
-
选择最佳部署选项。您可以将 Ignite 用作嵌入式或实际群集拓扑。它们都包含一些优点和缺点。当 Ignite 与应用程序在同一 JVM(嵌入式模式下)运行时,从缓存获取数据的网络往返行程是最少的。但是,在这种情况下,Ignite 使用相同的 JVM 资源以及应用程序,这可能会影响应用程序的性能。此外,在嵌入式模式下,如果应用程序死,Ignite 节点也会失败。另一方面,当 Ignite 节点在单独的 JVM 上运行时,从群集获取数据的网络开销最小。因此,如果您有内存占用量较小的 Web 应用程序,则可以考虑在同一 JVM 中使用 Ignite 节点。
-
使用堆上缓存获得最佳性能。默认情况下,Ignite 使用 Java 堆外存储缓存条目。使用堆外存储数据时,数据去序列化总是有一定的开销。为了缓解延迟并获得最大的性能,可以使用堆上缓存。您还应考虑到 Java 堆大小几乎有限,并且每当使用堆上缓存时,都会存在 GC(垃圾回收)开销。因此,每当使用少量的缓存时,请考虑使用堆上缓存,并且缓存条目几乎是常量。
-
尽可能使用原子缓存模式。如果不需要强的数据一致性,请考虑使用原子模式。在原子模式下,每个 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 成本。许多人认为缓存是使一切更快、更凉爽的简单方法。然而,正如实践所表明的,缓存的不正确使用只会使事情变得更糟。缓存是仅在正确使用时才能提高性能的机制。因此,在项目中实现之前,请记住这一点,在所有相关案例之前和之后进行测量。
如果您有任何意见或想法,请不要犹豫。这篇文章的部分取自阿帕奇点燃书。如果它让你感兴趣,请查看本书的其余部分,以了解更多信息。