SolrPerformancePlroblems

原文地址:https://cwiki.apache.org/confluence/display/SOLR/SolrPerformanceProblems

本文将回答下面的问题:

  1. 为什么Solr性能这么差。
  2. 为什么Solr启动时间那么长。
  3. 为什么SolrCloud在我的服务器表现正常的情况下出现故障。

本文尝试提供一些基本的信息。为了更好的理解设计的问题,请阅读其他资源,http://www.catb.org/~esr/faqs/smart-questions.html#introhttp://lucene.apache.org/solr/discussion.html

1 General information

影响Solr性能主要因素是RAM。Solr需要足够的内存做两件事情:一个是java堆,另一个是磁盘缓存。

另一个潜在的问题是很高的查询请求。有时候增加内存可以让solr处理更高的查询速度。如果支持更大的查询,你将需要多台机器上添加索引的多副本进行扩展。对于单例的Solr,或非云的client,可以使用SolrCloud,多副本的时候需要使用负载均衡。

强烈建议Solr运行在64位的Java上。64位java需要64位的操作系统,而64位操作系统需要64位的CPU。32位软件应将没有什么问题,但是32位java限制于2G的顿大小。本文后面部分将会讨论java堆。

1.1 SolrCloud

无论节点数量或可用资源数量多少,当集合数量达到数百个时,SolrCloud都会出现稳定性问题。对于成千上万个集合,集群的任何小问题都可能导致稳定性直线下降,可能在几十分钟内无法恢复。所以尽可能的保持集合数量较少。这些问题是由于SolrCloud需要在zookeeper上更新集群状态。正在试图解决此问题。在Solr4.x状态会保存一个“clusterstate.json”文件。后续版本5.x以后会给每个collection保存一个“state.json”,会在每个collection的znode下保存(/collections/my_collection/state.json)。

因为SolrCloud高度依赖Zookeeper,所以在遇见性能问题会导致操作时间超过zkClientTimeout(https://lucene.apache.org/solr/guide/6_6/solrcloud.html#SolrCloud-SolrCloud_Instance_Zookeeper_Params),引起不稳定。延长超时可能会缓解,但最好是解决根本的性能问题。默认超时时间为15秒,一般就足够了。

Zookeeper设计时就假设他能快速的访问他的数据。如果Zookeeper数据存储和solr的数据存储在相同磁盘上,那么solr的任何性能问题都将导致Zookeeper访问自己的数据出现延迟。这可能导致性能急速下降,每个zk超时后的恢复操作,会进一步导致超时。

Zookeeper会将数据保存在java堆中,所以磁盘的读取性能没有写入性能那么重要。如果磁盘缓存太小无法满足Solr本身的要求,并且zk和solr的数据在一块磁盘,则solr的大量磁盘访问会干扰zk的写入。最好给zk用快速磁盘(例如SSD)可以提升性能。强烈建议将solr和zk的磁盘隔离开。最好为所有zk节点配独立的服务器(至少3个节点),但也不是强要求。

SolrCloud:https://lucene.apache.org/solr/guide/6_6/solrcloud.html

2 High Request Rate

如果你的请求qps很高,通常会极大的影响性能,如果请求超过30qps,需要考虑给索引添加副本。每秒处理上千个请求需要大量的服务器。

处理高查询通常是在多个服务器上设置索引的多副本,并实现负载均衡。SolrCloud可以自动执行这些操作。但也有可能需要外部的负载均衡器。

3 RAM

3.1 OS Disk Cache

索引更新,依赖于读取和写入的速度。搜索时快速随机读取更重要。如果需要满足这些需求,最好的办法是有大磁盘缓存(http://en.wikipedia.org/wiki/Page_cache)。查看https://blog.thetaphi.de/2012/07/use-lucenes-mmapdirectory-on-64bit.html

还可以使用固态硬盘加快Solr的速度,但这并不是完整的替代方案,请查看文档里关于SSD的部分。

简而言之,你需要有足够的内存可以用于索引的高速缓存。假设Solr索引大小为8G,Solr的jvm和其他程序需要4G,那么理想的服务器内存为12G。可以让服务器只有8G内存但是这不能保证缓存命中率。

如果你希望查询延迟尽可能的底,那么最好有足够的内存能缓存所有的索引。如果不需要低延迟,那么也就不需要缓存整个索引。

低延迟的要求并不确定,和索引的内容和查询都有关系。如果索引有很多字段,

(警告)非常重要的是,没有用于确定在高性能下最小内存的计算公式。

Special note regarding the optimize operation

优化索引时会使用大量的磁盘I/O。如果你没有足够的内存来缓存索引,那么优化操作会对正常的Solr造成很大的影响。如果需要经常优化,则需要能缓存100%索引的RAM。如果你有足够的RAM能同时缓存索引的原始版本和优化版本,则优化过程性能是最好的。当主服务器产生大量合并优化时,也会复制到从服务器。

3.2 Java Heap

Java堆是Java程序实际运行所需的内存。

在日志中发现有OutOfMemoryError(OOM)异常,则java进程就会结束。如果看到此问题,则说明Solr不能申请到更多的内存。处理OOM的两种方法,一种是增加机器的内存,另一种是减少solr的jvm内存。通常发生OOM是因为使用的线程/进程数过高。

Solr中的某些配置需要大量的堆内存。包括:

  1. 大索引。
  2. 频繁更新。
  3. 超大文档。
  4. 频繁使用facet。
  5. 排序参数大量不同。
  6. Solr的大缓存。
  7. RAMBufferSizeMB较大。
  8. 使用Lucene的RAMDirectoryFactory。

How much heap space do I need?

简单的说:这没有标准的答案。因为你需要足够大的JVM,这样就不会有OOM和垃圾回收问题,但是又不能太大以免浪费和垃圾回收带来的stop world。

复杂的说:必须经过试验。使用GUI工具(jconsole、jvisulavm),可以连接正在运行的solr实例,查看堆的使用情况。对于长期运行的JVM堆,可以使用SPM工具长期监控内存空间和垃圾回收。JVM Memory Poll Monitoring介绍了查看内存和避免OOM。

http://docs.oracle.com/javase/6/docs/technotes/guides/management/jconsole.html

http://docs.oracle.com/javase/6/docs/technotes/tools/share/jvisualvm.html

http://sematext.com/spm

http://blog.sematext.com/2013/10/21/jvm-memory-pool-monitoring/

http://docs.oracle.com/javase/1.5.0/docs/guide/management/jconsole.html#memory

在jconsole例子中显示一种典型的内存使用攀升,然后垃圾回收释放了内存。你的查询和更新量决定了内存会有多少document。一种经验法则:查看Solr每秒的查询的document,如果每分钟垃圾回收超过该值,则jvm堆太小。经过不断的调整会是垃圾回收能快速工作。

如果Solr服务有很高的查询和更新,则JVM的垃圾回收的锯齿低点就是所需的最小内存。尽量将最大堆设置成改值的125%~150%之间,重复测试查看监控锯齿模式中低点是否明显高于以前,或垃圾回收是否频繁。如果是则表示还要继续调大堆。

另一个确定堆大小设置的是否合理是使用Solr打印的GC日志。gceasy可以帮助分析,和查看Solr的帮助文档。

http://lucene.apache.org/solr/discussion.html

http://gceasy.io/

其他经验法则:通常堆越大越好。但是太大垃圾回收时间会很长。

Reducing heap requirements

警告:调整垃圾回收参数不会减少Solr对内存的需要!他可以加快GC,但是无法降低内存使用。它会是锯齿形内存图的高点降低,但不会影响低点。如果你遇到的是内存不足,则调整GC参数是没有用的。更有效的垃圾回收只会让程序花费较长的时候产生OOM,但是不能避免。

下面列表,给出需要大量堆内存的因素,如何减少堆的使用:

  • 将大索引进行切分 - 放到多个shard中:

  • 比较简单的办法是使用SolrCloud。你可能需要重建索引。

  • 这实际上并不会减少索引的总体内存需求(可能还会增加),但是他会分布在多个服务器上,因此每个服务器的内存需求较低。为了实现冗余,不同服务器上要增加副本。

  • 如果查询效率低,则将多个shard放在单个服务器上会更好。随着查询的增加,每个服务器只有replicas会更好。

  • 不要存储所有的字段,特别是大字段。

  • 让你的程序从原始数据源加载详细数据,而不是从solr。

  • 需要注意,这意味着不能使用Atomic Updates。

  • 你还可以使用docValues在经常sorting/facet字段上。

  • 减少用于sort的数量。docValues会对facet和sort的性能和内存使用产生积极影响。

  • 减少solr缓存大小。

  • 减少RAMBufferSizeMB。最新版本的Solr默认是100.如果你有多个core。这个值比较重要,因为每个core都会使用缓冲区。

  • 不要使用RAMDirectoryFactory - 而是使用系统默认的并安装足够的RAM,让操作系统可以缓存整个索引。

GC pause problems

如果你有很大的堆(大于2GB),垃圾回收的暂停是主要的问题。这通常是因为要Full GC要进行“stop world”引起的 - 暂停所有进程执行清理内存。主要有两个解决方案:一种是使用上页面的JDK收费工具例如Zing,另一种是使用免费的JDK。GC调节是一种艺术,对别人有效并不一定对你也有效。

对于Solr使用CMS进行垃圾回收是比较好的,单对于java7以上版本G1是更好的选择。

使用CMD需要手动调整各代的大小。G1会自动调节大小,强制设置会导致性能下降。

如果最大堆设置的太小,则会遇到不同的垃圾回收问题。通常比大堆问题严重:每次Solr申请内存都需要进行Full GC,这样会导致非常慢。堆大小和GC很难调整的很难完美。

Asking for too many rows

如果想快速的查询rows=9999999,在5百万-1000万的数据集查询,会引起很多Full GC。既是实际命中的很少,但是客户端请求大量数据导致分配大量的Java对象(每行一个ScoreDoc)并保存到内存中。将产生大量的GC,并触发Full GC。有时候增加堆会有提升,但会经常进行GC。阅读下面文章会有一些建议。

https://sbdevel.wordpress.com/2015/10/05/speeding-up-core-search/

一种简单解决方案方案是减少rows,或者使用export、cursorMark(流式传输)。

如果你无法控制客户端,可以在solrconfig的invariants设置rows,或者自定义SearchComponent来自定义允许的最大rows。

Tools and Garbage Collection

除非是由于堆太小,否则JVisualVM和JConsole不会显示GC暂停问题。你只能看总计或者平均值。

可以使用下面工具。

http://www.azulsystems.com/jHiccup

https://code.google.com/p/gclogviewer/

https://github.com/chewiebug/GCViewer

3.3 SSD

固态硬盘,超高的传输速度,几乎解决了随机访问数据的延迟问题。

购买高级磁盘之前,需要考虑的是你如果有足够的内存进行缓存,那么磁盘的速度对查询性能影响不大。如果没有足够的内存进行缓存,则磁盘的速度将受影响,但是添加内存会提升性能。

在内存不足的情况下,将索引放到SSD上,则性能会比机械盘会好。如果当前Solr服务器正在使用SSD并发生性能瓶颈,则换更好的SSD也不一定能解决。

通常SSD被说成代替磁盘缓存的RAM。也对也不对。尽管SSD速度惊人,但是RAM(操作系统的磁盘缓存)的速度仍然很高,并且RAM在基于SSD的系统性能中仍然发挥着重要作用。SSD可能不用和机械盘一样多的RAM,但是必须要是用。是用机械盘时,需要50%至100%作为缓存。是用SSD时,如果索引小,则可以减少到25%到50%。

一种解决Solr问题的方法是将您的操作系统和Solr本身放在RAID的常规磁盘上,然后将索引数据放在一个单独的SSD上。 如果SSD发生故障,您的冗余服务器仍将在那里处理请求。

3.4 Asking for help on a memory/performance issue

如果你需要在性能问题寻求帮助,那么需要确定的首页问题是是否有能力让内存获取合理的性能。从操作系统获取信息有助于确定这一点。

4 Extreme scaling

当Solr索引的数量达到几十亿,查询又很高,则对硬件的要求会变得很苛刻。这个规模的索引处理会变得很安规,因为需要很多的服务器,每个服务器都需要很大的内存。SSD变得更加关键,成本会很高。

5 Slow startup

启动缓慢的主要原因有两个。一个是事务日志,一个是suggester组件。

5.1 Slow startup due to the transaction log

尽快可能还有其他问题,但是此问题最常见的原因是在Solr4.0引入的updateLog功能。问题不在于功能本身,而是取决于功能打开时如何配置和使用,transaction log可能会失控。

updateLog功能是为了更新添加事务日志。使用正确,事务日志可以带来好处,SolrCloud需要使用。还有软提交的概念。

如果大量的文档更新发送到索引而不进行提交或只进行软提交,则事务日志将变得很大。Solr启动时将replay事务日志来确保数据不会丢失。对于非常大的日志这会非常慢。使用DataImportHandler大量导入数据会导致日志较大,最好执行一次硬提交。

要解决启动缓慢问题,需要减少事务日志的大小。唯一的办法是经常进行硬提交。硬提交将关闭当前的事务日志并启动一个新的日志。Solr只会保留足够的日志确保可以还原最后100个文档。单不能拆分日志文件,因此如果日志文件非常大则必须保留整个内容在启动的时候进行replay。小型事务日志进行replay速度会很快,因此最好保持他很小。

解决方案是在solrconfig.xml的update handler打开autoCommit:

<updateHandler class="solr.DirectUpdateHandler2">

<autoCommit>

<maxDocs>25000</maxDocs>

<maxTime>300000</maxTime>

<openSearcher>false</openSearcher>

</autoCommit>

<updateLog />

</updateHandler>

大家在进行大量更新而不提交,可能是因为想在全部更新之前是不可见的。此要求需要修改openSearcher=false。使用此选项需要发送硬提交或软提交命令,让其可见。

你可以可以调整autoCommit中的maxDocs和maxTime参数。默认(25000个文档或5分钟)是一个很好的参考,当然在更新量非常高或非常低的情况下,也需要进行调整。

5.2 Slow startup due to the suggester component

如果索引较大,并且在solrconfig.xml中启用了suggester组件,则可能会导致启动缓慢。从4.10.2版本开始默认启动此组件。在5.1版本对此问题进行了修改。

6 Slow commits

通常,打开新的searcher才会提交很慢。提交缓慢的原因包括:

Solr的缓存autowarmCount设置较大。

堆大小问题。堆太大导致问题很少发生,但是会持续发生。

非常频繁的提交。

综上所述,都是没有足够的OS内存用于磁盘缓存。

如果Solr缓存的autowarmCount值较大,则可能会话很长时间才能进行缓存预热。filterCache的升温速度特别慢。解决方案是减少autowarmCount,或减少查询复杂度。

如果你频繁提交,则可以在上次提交完成之前发送新的提交。如果solrconfig.xml中的maxWarmingSearchers很高,则最终可能会使多个新的searcher进行预热,这是高I/O的工作。

如果在不打开新的searcher时提交缓慢,则可能是由于一般性能问题。

7 Slow indexing

慢速索引的原因很多。大多数情况下,solr不会变慢。慢索引最大的原因是从源系统检索信息的速度。

导致索引编制缓慢的其他可能问题包括:在每个更新请求之后提交,在每个更新请求中一次发送一个文档而不是批量处理他们,以及使用一个线程进行索引。这些是Solr外部的问题。可能的解决方案是使用IgnoreCommitOptimizeUpdateProcessorFactory忽略来自clien的提交,而是使用autoCommit的设置。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容