Solr 4.5 在后续查询中使用了过多内存,GC 运行导致超时

Solr 4.5 在后续查询中使用了过多内存,GC 运行导致超时

Solr 4.5 上有一个索引,其中包含约 50K 个文档,占用约 4Gb 磁盘空间。JVM 可用的物理 RAM 为 6Gb(服务器总共 10Gb),操作系统为 64 位 CentOS 5。

其中一个应用程序查询循环中多次索引,一个请求在前一个请求完成后立即发送,中间几乎没有延迟,但仍然不是同时发送的。

这些查询都是相同的,并且符合以下简单模式:

  • q=description:“关键字”或订单:“关键字”或目录:“关键字”
  • fl=id、分数、姓名、国家
  • 排序=分数降序
  • 重量=json
  • 缩进=真
  • 开始=0
  • 行=100

(所有字段q都是索引标记文本)

在收到相对较少数量的此类查询(有时是第 3 次查询之后,有时是第 5 次查询之后等)后,Solr 端的垃圾收集器就会启动,因为所有内存都处于繁忙状态。这会导致 Solr 响应前有几秒钟的延迟,从而导致发送请求的应用程序因超时而中止。

如果应用程序在发送的后续查询之间等待大约 1 秒钟,则所有查询都会快速完成,并且 RAM 不会达到最大值;但是查询发送得越快,下一个查询导致触发 GC 和不必要的超时的变化就越大。

在旧版本的 Solr(1.4)中,相同的索引(由相同的应用程序使用相同的数据构建)采用相同的使用模式是完全没问题的。

增加缓存大小solrconfig.xml似乎没有太大效果,但将rows参数从 100 减少到 10 可以降低超时的可能性,但并非完全不可能。queryResultWindowSize配置中的设置为默认值 20。

我猜观察到的行为可能有多个原因,而我给出的细节不够。如果是这样,我需要进行哪些更改或分析才能缩小范围?

答案1

这就是 Java 的本质:垃圾收集意味着整个世界停止。

我所知道的可接受的解决方案一般都很糟糕:

  1. 添加更多 RAM(这样您可以在内存压力强制自动 GC 之前执行更多查询);
  2. 添加更多服务器(以分散负载);或
  3. 手动鼓励 GC 更频繁地运行(因此需要做的事情更少,完成得更快)

由于您在升级到新版本的 Solr 后才开始遇到问题,因此您可能需要查看他们的邮件列表在他们的问题追踪器中看看这是否是更高版本中已解决的已知问题。
如果您想分析和调试应用程序本身,这实际上更像是 Stack Overflow 问题——可能是您的 Solr 存在一些次优问题(在您的查询或应用程序中),这导致它使用的 RAM 比它需要的要多。

答案2

Yuriy,我在 Azul Systems 工作。去年,我们在基准测试中对 Zing 虚拟机与 Lucene 进行了测试。我们编写的解决方案简介在第二页的图表中显示了代表性的延迟统计数据:http://www.azulsystems.com/partners/apache-lucene-solr

Zing 垃圾收集器“C4”与 Hotspot 中的不同。Zing 下的垃圾收集意味着整个世界不会停止。相反,Java 变量线程继续运行,GC 操作并行运行,通常在不同的内核上。Zing 中没有停止世界模式,无论是在主要 GC 策略中还是作为后备,无论是在新一代和旧一代收集器中。

我不能说我们已经将 Solr 4.5 视为罪魁祸首。如果您确定 Solr 或您的应用程序没有错误,并且在分类后仍然有 GC 暂停,请考虑查看 Zing:http://www.azulsystems.com/products/zing/whatisit

Voretaq7 对替代品糟糕的评论一定不包括 C4 或 Zing。至少我希望如此。

祝你好运。

马特

相关内容