可能的 Apache Ignite 内存泄漏?

huangapple go评论89阅读模式
英文:

Possible Memory leak in Apache Ignite?

问题

我试图将Ignite用作内存中的键值对数据库,值的范围从50MB到800MB不等。看起来Ignite通过JVM分配堆空间,即使缓存条目在堆外,被清除,在没有连接的客户端和没有运行的操作的情况下,它也永远不会清理这些空间。由于我的机器无法处理这样的内存消耗,因此我正在寻找一种清理一些内存的方法。

我的测试场景如下:

  • Ignite版本2.9
  • 使用OpenJDK 11运行

我通过Python脚本和pyignite轻客户端在本地测试Ignite:

client = Client()
client.connect('localhost', 10800)

my_cache = client.get_or_create_cache('default')
my_cache.clear()

data = createData() #创建800 000 000字节的测试数据

def put(caches):
  i = caches
  while i > 0:
    my_cache.put('my key' + str(i), data)
    i -= 1

put(5)

my_cache.remove_all()
my_cache.destroy()
client.close()

脚本将800MB的数据顺序写入5个不同的缓存条目。下面的快照显示了Ignite的堆如何增长到其峰值点,这本身是可以理解的,但在执行GC后仍然保持在约10GB左右:

Ignite堆

在使用相同数据进行第二次测试后,经过GC后不会导致更大的堆内存消耗,这使我相信Ignite会在内部为传入的数据分配缓冲区,这些缓冲区的大小与数据的大小相对应。这种内存消耗实在是太大了,我的机器无法长期处理这种情况。

Ignite的配置非常简单:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="ignite.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
        
        <!-- 持久化内存配置。 -->
        <property name="dataStorageConfiguration">
            <bean class="org.apache.ignite.configuration.DataStorageConfiguration">
                <property name="dataRegionConfigurations">
                    <list>
                    <bean class="org.apache.ignite.configuration.DataRegionConfiguration">
                        <!-- 自定义区域名称。 -->
                        <property name="name" value="10GB_Region"/>
                        <!-- 100MB初始大小。 -->
                        <property name="initialSize" value="#{100L * 1024 * 1024}"/>
                        <!-- 10GB最大大小。 -->
                        <property name="maxSize" value="#{10096L * 1024 * 1024}"/>
                    </bean>
                    
                    </list>
                </property>
                    <!-- 重新定义默认区域的设置 -->
                    <property name="defaultDataRegionConfiguration">
                        <bean class="org.apache.ignite.configuration.DataRegionConfiguration">
                            <property name="name" value="Default_Region"/>
                            <property name="maxSize" value="#{5L * 1024 * 1024 * 1024}"/>
                        </bean>
                    </property>
                </bean>
            </property>
    
        <property name="cacheConfiguration">
            <list>
                <!-- 分区缓存示例配置(原子模式)。 -->
                <bean class="org.apache.ignite.configuration.CacheConfiguration">
                    <property name="name" value="default"/>
                    <property name="atomicityMode" value="ATOMIC"/>
                    <property name="backups" value="1"/>
                    <property name="dataRegionName" value="10GB_Region"/>
                </bean>
            </list>
        </property>
    
        <property name="discoverySpi">
            <bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">
                <property name="ipFinder">
                    <bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMulticastIpFinder">
                        <property name="addresses">
                            <list>
                                <value>127.0.0.1:47500..47509</value>
                            </list>
                        </property>
                    </bean>
    
                </property>
            </bean>
        </property>
    </bean>
</beans>
  • Ignite Visor明确表示缓存是堆外的。
  • VisualVM直方图显示,98%的活动字节映射到byte[]。
  • 似乎有客户端连接器和数据流水线线程保持打开状态,每个放入缓存的操作对应一个线程,但我不确定它们需要多少堆内存。
  • 在my_cache.put中提供值提示并没有帮助。
  • cache.clear()、cache.destroy()并没有帮助(也不应该,因为缓存是堆外的)。

非常感谢您的帮助!

英文:

I am trying to use Ignite as an in-memory database for key-value pairs with values ranging from 50MB to 800MB. It looks like Ignite allocates heap space through the JVM that it never cleans up, even if the cache entries are off heap, are cleared, there are no connected clients and no running operations. My machine would not be able to handle such memory consumption, hence I am looking for a way to clean up some memory.

My test scenario is as follows:

  • Ignite version 2.9
  • Running with OpenJDK 11

I am testing Ignite locally through a python script with the pyignite thin client:

client = Client()
client.connect(&#39;localhost&#39;, 10800)
my_cache = client.get_or_create_cache(&#39;default&#39;)
my_cache.clear()
data = createData() #creates 800 000 000 bytes test data
def put(caches):
i = caches
while i &gt; 0:
my_cache.put(&#39;my key&#39; + str(i), data)
i -= 1
put(5)
my_cache.remove_all()
my_cache.destroy()
client.close()

The script writes the 800 MB data sequentially in 5 different cache entries. The following snapshot illustrates how Ignite's Heap grows to its peak point, which by itself is understandable, but afterwards stays around 10GB even after performing GC:

Ignite heap

Performing a second test run with the same data does not result in bigger heap consumption after GC, which leads me to believe that Ignite allocates buffers for the incoming data internally, which correspond with the size of the data. This memory consumption is simply too great and my machine would not be able to deal with it in the long run.

The ignite configuration is quite simple:

&lt;beans xmlns=&quot;http://www.springframework.org/schema/beans&quot;
xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
xsi:schemaLocation=&quot;
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
&lt;bean id=&quot;ignite.cfg&quot; class=&quot;org.apache.ignite.configuration.IgniteConfiguration&quot;&gt;
&lt;!-- Durable memory configuration. --&gt;
&lt;property name=&quot;dataStorageConfiguration&quot;&gt;
&lt;bean class=&quot;org.apache.ignite.configuration.DataStorageConfiguration&quot;&gt;
&lt;property name=&quot;dataRegionConfigurations&quot;&gt;
&lt;list&gt;
&lt;bean class=&quot;org.apache.ignite.configuration.DataRegionConfiguration&quot;&gt;
&lt;!-- Custom region name. --&gt;
&lt;property name=&quot;name&quot; value=&quot;10GB_Region&quot;/&gt;
&lt;!-- 100 MB initial size. --&gt;
&lt;property name=&quot;initialSize&quot; value=&quot;#{100L * 1024 * 1024}&quot;/&gt;
&lt;!-- 10GB maximum size. --&gt;
&lt;property name=&quot;maxSize&quot; value=&quot;#{10096L * 1024 * 1024}&quot;/&gt;
&lt;/bean&gt;
&lt;/list&gt;
&lt;/property&gt;
&lt;!-- Redefining the default region&#39;s settings --&gt;
&lt;property name=&quot;defaultDataRegionConfiguration&quot;&gt;
&lt;bean class=&quot;org.apache.ignite.configuration.DataRegionConfiguration&quot;&gt;
&lt;property name=&quot;name&quot; value=&quot;Default_Region&quot;/&gt;
&lt;property name=&quot;maxSize&quot; value=&quot;#{5L * 1024 * 1024 * 1024}&quot;/&gt;
&lt;/bean&gt;
&lt;/property&gt;
&lt;/bean&gt;
&lt;/property&gt;
&lt;property name=&quot;cacheConfiguration&quot;&gt;
&lt;list&gt;
&lt;!-- Partitioned cache example configuration (Atomic mode). --&gt;
&lt;bean class=&quot;org.apache.ignite.configuration.CacheConfiguration&quot;&gt;
&lt;property name=&quot;name&quot; value=&quot;default&quot;/&gt;
&lt;property name=&quot;atomicityMode&quot; value=&quot;ATOMIC&quot;/&gt;
&lt;property name=&quot;backups&quot; value=&quot;1&quot;/&gt;
&lt;property name=&quot;dataRegionName&quot; value=&quot;10GB_Region&quot;/&gt;
&lt;/bean&gt;
&lt;/list&gt;
&lt;/property&gt;
&lt;property name=&quot;discoverySpi&quot;&gt;
&lt;bean class=&quot;org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi&quot;&gt;
&lt;property name=&quot;ipFinder&quot;&gt;
&lt;bean class=&quot;org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMulticastIpFinder&quot;&gt;
&lt;property name=&quot;addresses&quot;&gt;
&lt;list&gt;
&lt;value&gt;127.0.0.1:47500..47509&lt;/value&gt;
&lt;/list&gt;
&lt;/property&gt;
&lt;/bean&gt;
&lt;/property&gt;
&lt;/bean&gt;
&lt;/property&gt;
&lt;/bean&gt;
&lt;/beans&gt;
  • ignite visor specifically says the the cache is off-heap
  • VisualVM histogram says that 98% of live Bytes are mapped to byte[]
  • it seems that there are client-connector and data-streamer-stripe threads that remain open, one per put operation in the cache, but I am not sure how much heap they require
  • providing value hints in my_cache.put does not help
  • cache.clear(), cache.destroy() does not help (and it should not, as the cache is off heap)

Any help will be very much appreciated!

答案1

得分: 1

  1. Apache Ignite默认情况下不在堆上保存数据,而是会将数据保存在堆外。
  2. Apache Ignite确实不会在删除数据时释放堆外内存,但会在新数据被摄取时重新使用该堆外内存。
  3. 目前还不清楚为什么您的工具会报告使用了大约16GB的堆内存,因为根据提供的配置,Ignite不应该使用超过几百MB的堆内存。如果这不仅仅是堆内存,而是所有的RAM,那就没问题。您应该预期分配10GB。为什么Size字段报告的比这个更多,目前还不清楚。
英文:
  1. Apache Ignite does not hold data on heap by default, instead, it will hold data off-heap.
  2. Apahce Ignite will indeed not release off-heap when data is removed, but it will allow to re-use said off-heap when new data is ingested.
  3. It's not clear at all why your tool would report the use of ~16G heap since Ignite should not use more than a few hundred MBs with the provided config. If that's not just heap but all RAM, then there you go. You should expect that 10G should be allocated. Why does it report more in Size field is not clear.

答案2

得分: 0

对于任何对此感兴趣并为长时间等待道歉,但在与Ignite邮件列表联系后,我确实得到了我的问题答案。显然,Ignite从未旨在在单个查询中处理如此大量的数据。所描述的行为是预期的,并且与将数据分成包并将其发送到其他节点或将其放入持久性存储有关。建议的解决方案是将数据分成更小的块。由于在我这种情况下目前不可能实现这一点,我不得不放弃使用Ignite并寻找其他方法来存储我的数据。

英文:

My apologies for the long delay to anyone who is interested, but I did get an answer to my question after contacting the Ignite mailing list. Apparently Ignite was never meant to consume such large amounts of data in a single query. The described behavior is expect and has to do with dividing the data into packages and sending it to other nodes or putting it into persistence. The suggested solution is to chunk the data into much smaller bits. Since this is currently not possible in my case, I had let go of Ignite and look for other approaches to store my data.

huangapple
  • 本文由 发表于 2020年10月27日 16:18:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/64550479.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定