我们使用Pivotal Gemfire作为我们数据的缓存。最近我们从gemfire 8.2.1迁移到9.5.1,具有完全相同的区域,数据和索引。但是特别是一个区域的索引创建占用了太多的时间,其中输入数量为7284500.我们使用Spring数据gemfire v2.4.1.RELEASE来定义缓存服务器。以下是有问题区域的配置:
<gfe:replicated-region id="someRegion"
shortcut="REPLICATE_PERSISTENT" concurrency-level=100
persistent="true" disk-synchronous="true" statistics="true">
<gfe:eviction action="OVERFLOW_TO_DISK" type="ENTRY_COUNT"
threshold=1000></gfe:eviction>
</gfe:replicated-region>
以下是索引定义:
<gfe:index id="someRegion_idx1" expression="o1.var1" from="/someRegion o1" />
<gfe:index id="someRegion_idx2" expression="o2.var2" from="/someRegion o2"/>
<gfe:index id="someRegion_idx3" expression="o3.var3" from="/someRegion o3"/>
<gfe:index id="someRegion_idx4" expression="o4.var4" from="/someRegion o4"/>
<gfe:index id="someRegion_idx5" expression="o5.var5" from="/someRegion o5"/>
<gfe:index id="someRegion_idx6" expression="o6.var6" from="/someRegion o6"/>
<gfe:index id="someRegion_idx7" expression="o7.var7" from="/someRegion o7"/>
<gfe:index id="someRegion_idx8" expression="o8.var8" from="/someRegion o8"/>
下面是缓存定义:
<gfe:cache
properties-ref="gemfireProperties"
close="true"
critical-heap-percentage=85
eviction-heap-percentage=75
pdx-serializer-ref="pdxSerializer"
pdx-persistent="true"
pdx-read-serialized="true"
pdx-ignore-unread-fields="false" />
以下是Java参数:
java -Xms50G -Xmx80G -XX:+UseConcMarkSweepGC
-XX:+UseCMSInitiatingOccupancyOnly
-XX:CMSInitiatingOccupancyFraction=70
-XX:+ScavengeBeforeFullGC -XX:+CMSScavengeBeforeRemark
-XX:+UseParNewGC -XX:+UseLargePages
-XX:+DisableExplicitGC
-Ddw.appname=$APPNAME \
-Dgemfire.Query.VERBOSE=true \
-Dgemfire.QueryService.allowUntrustedMethodInvocation=true \
-DDistributionManager.MAX_THREADS=20 \
-DDistributionManager.MAX_FE_THREADS=10 \
-Dcom.sun.management.jmxremote \
-Dcom.sun.management.jmxremote.port=11809 \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false \
-Dconfig=/config/location/ \
com.my.package.cacheServer
在没有XX:+ScavengeBeforeFullGC -XX:+CMSScavengeBeforeRemark -XX:+DisableExplicitGC
的情况下运行时,我们曾经在应用索引时遇到以下错误:
org.apache.geode.ForcedDisconnectException:成员没有响应心跳请求gemfire的关键
我们尝试将member-timeout
属性从5000增加到300000,但同样的问题仍然存在。
添加上述GC相关的java参数后,每个索引大约需要24分钟才能应用,但这次没有错误。这导致服务器花费太多时间与大约15个其他区域一起出现。其他地区没有这样的问题。(该地区的数据量最大。其他地区的入境人数约为500K至3M)
我从配置中看到一些需要调整的东西。对于其中一些我需要推测,因为我不知道你的一般终身堆消耗。
将NewSize和MaxNewSize设置为9gb将SurvivorRatio设置为1将TargetSurvivorRatio设置为85添加PrintTenuringDistribution标志以帮助我们进行微调。
关于索引创建时间 - 正如David指出的那样,您已将此区域配置为几乎所有数据都在磁盘上。
这将使索引创建更加昂贵,因为索引创建过程必须从磁盘读取所有条目。
但是,如果在索引上使用define
标志,则可以使用此配置更快地创建索引
<gfe:index id="someRegion_idx3" expression="o3.var3" from="/someRegion o3" define="true"/>
这将导致在ApplicationContext初始化结束时在一次传递中创建所有索引。所以希望你的总时间将接近24分钟,因为GemFire只需扫描一次磁盘上的所有数据。
有关定义索引的更多信息,请参阅https://docs.spring.io/spring-gemfire/docs/current/reference/html/#_defining_indexes。
这并没有真正解释你的垃圾收集问题 - 我会在那里查看David的答案以获取更多细节。