Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

通过对日志和内存 dump 的分析,发现分布式 RaftLogManager 中的内存缓存超出了阈值。在探究内存缓存超出阈值的原因时,发现主要有以下四个问题:

  • 分布式进程中单机内存和 RaftLog 内存没有统一考虑管理,即单机认为自己得到了全部堆内存进行分配,而分布式又在一些地方额外分配了内存并进行了内存控制,这导致分布式进程对自己拥有内存的认知一开始就大于实际的堆内存,从而使得内存一开始写入就比较紧张。内存没有统一考虑管理,即单机认为自己得到了全部堆内存进行分配,而分布式又在一些地方额外分配了内存并进行了内存控制,这导致分布式进程对自己拥有内存的认知一开始就大于实际的堆内存,从而使得内存一开始读写就比较紧张。
  • RaftLog 模块自身做了简单的内存控制策略,但只是针对已 commit 日志做的,未 commit 的日志没有通过阻写的方式来实现完备的内存控制。
  • RaftLog 模块的内存控制与单机的内存控制产生了正反馈导致系统崩盘。极端情况下,由于内存不够,单机状态机受单机内存控制模块影响导致 apply 日志过慢,然而 RaftLog 模块的清理内存线程只能清理 applyIndex 之后的日志,这导致 RaftLog 模块的内存控制几乎失效,无法清理内存中的日志。两者的双向作用共同导致了问题的进一步恶化。模块的内存控制几乎失效,无法清理内存中的日志,导致内存进一步紧张,这又导致单机 apply 日志更慢。两者的双向作用共同导致了问题的进一步恶化。
  • RaftLog 模块的后台清理内存线程默认被关闭了,导致目前只有在 commit 的时候才会去检验内存,这可能使得内存释放不及时。当然,即使有它也不能完全避免前面提到的问题。

...