sofastack / sofa-jraft

A production-grade java implementation of RAFT consensus algorithm.
https://www.sofastack.tech/projects/sofa-jraft/
Apache License 2.0
3.57k stars 1.14k forks source link

LogManagerImpl里的logsInMemory是否有内存泄露风险 #840

Open jackjoesh opened 2 years ago

jackjoesh commented 2 years ago

LogManagerImpl里的logsInMemory是否有内存泄露风险? 重现原因: 1 如果follower重启后,需要append log的非常多,比如几亿条(某些原因leader长时间没有snapshot),那logsInMemory里就会添加很多到内存里 2 而在NodeImpl的handleAppendEntriesRequest逻辑里,是用JRaft-LogManager-Disruptor队列的空间大小来判断是否足够接收log的,不会去判断logsInMemory内存空间是否足够 3 logsInMemory的清理需要等到状态机apply或者打snapshot的时候,相当于收到log到apply这段时间内,内存是无法清理的,且apply速度一般不会那么快。

实测下来,大概logsInMemory只需要缓存36万个segment,内存占用就可以突破13GB,会内存泄露。内存dump如下:

image

image

out of memory日志: 2022-06-05 16:04:52 [JRaft-LogManager-Disruptor-0] ERROR LogExceptionHandler:64 - Handle LogManagerImpl disruptor event error, event is com.alipay.sofa.jraft.storage.impl.LogManagerImpl$StableClosureEvent@7d4d317b java.lang.OutOfMemoryError: Java heap space

是否应该考虑加入对logsInMemory空间限制的保护?

killme2008 commented 2 years ago

确实存在这样的风险,需要加一个硬性限制,或者软性限制(比如交换到堆外空间等),降低内存和 gc 压力。

ReycoLi commented 1 year ago

请问调小JRaft-LogManager-Disruptor队列的空间大小会缓解吗 @killme2008