Solr Suggester字典构建失败,Java heap space错误求助
看起来你在处理1000万+数据的Solr自动补全时踩了两个核心大坑:内存溢出和建议器构建失败,我之前也处理过类似的海量数据补全场景,接下来帮你拆解问题并给出针对性的修复方案:
一、内存溢出的核心原因
你当前用的FuzzyLookupFactory是基于FST(有限状态机)构建建议字典的,它会把整个字典的所有词项加载到内存来生成FST——而你的autocomplete字段因为EdgeNGram的配置(minGramSize=1),每个title会生成1到25长度的前缀词项,千万级数据会让词量爆炸式增长,4G堆内存完全扛不住。再加上buildOnStartup=true让Solr启动时就强制构建,内存直接被榨干导致OOM。
二、分步修复方案
1. 替换建议器实现:用AnalyzingInfixLookupFactory替代FuzzyLookupFactory
FuzzyLookupFactory只适合小数据量的模糊补全,而AnalyzingInfixLookupFactory是专为大数据量设计的——它不需要把整个字典加载到内存,直接基于索引字段做查询,内存占用能降到原来的几十分之一,同时支持前缀/中缀补全,完全满足你输入"foob"返回"foobar company"的需求。
修改solrconfig.xml中的suggest组件:
<searchComponent name="suggest" class="solr.SuggestComponent"> <lst name="suggester"> <str name="name">suggest</str> <!-- 替换为大数据量友好的实现 --> <str name="lookupImpl">AnalyzingInfixLookupFactory</str> <!-- 不需要storeDir,直接复用索引数据 --> <str name="dictionaryImpl">DocumentDictionaryFactory</str> <str name="field">autocomplete</str> <str name="suggestAnalyzerFieldType">autocomplete</str> <!-- 关闭启动/优化时自动构建,避免内存过载 --> <str name="buildOnOptimize">false</str> <str name="buildOnStartup">false</str> <str name="buildOnCommit">false</str> <!-- 可选:如果需要模糊补全,设置编辑距离(1足够覆盖大部分场景) --> <str name="fuzzyEditDistance">1</str> </lst> </searchComponent>
2. 优化autocomplete字段的索引逻辑
你当前的minGramSize="1"会生成大量无意义的单字符前缀(比如每个title的第一个字),这会极大增加索引体积和查询词项数。建议把minGramSize调整为2或3,只生成有实际意义的前缀:
<fieldType name="autocomplete" class="solr.TextField" positionIncrementGap="100"> <analyzer type="index"> <tokenizer class="solr.KeywordTokenizerFactory"/> <filter class="solr.LowerCaseFilterFactory"/> <!-- 从1改成3,减少无意义前缀的生成 --> <filter class="solr.EdgeNGramFilterFactory" minGramSize="3" maxGramSize="25" /> </analyzer> <analyzer type="query"> <tokenizer class="solr.KeywordTokenizerFactory"/> <filter class="solr.LowerCaseFilterFactory"/> </analyzer> </fieldType>
3. 调整Solr内存配置
即使换了Lookup实现,千万级数据还是需要合理的内存分配:
- 把Solr的堆内存调整为
-Xms4g -Xmx6g(你的电脑有8G内存,给Solr分配6G是安全的,剩下2G留给系统和其他进程) - 加上
-XX:+UseG1GC参数,优化大内存下的垃圾回收性能
4. 重新索引并手动构建建议器
修改配置后按以下步骤操作:
- 停止Solr服务
- 删除core数据目录下的
index和suggester_fuzzy_dir文件夹 - 启动Solr服务
- 执行Rails的Sunspot重索引命令:
bundle exec rake sunspot:solr:reindex - 手动触发建议器构建:访问
http://你的Solr地址/suggesthandler?suggest.build=true(这时候不会再OOM了)
三、验证自动补全功能
构建完成后,用以下请求测试:
http://你的Solr地址/suggesthandler?suggest.q=foob&suggest.count=10
应该能正常返回包含"foobar company"的建议结果。
额外注意事项
- 千万级数据不要开启
buildOnCommit=true,否则每次索引提交都会触发建议器构建,严重影响性能,建议在凌晨低峰期手动构建或用定时任务执行。 - 如果title字段有大量重复值,可以在Solr中配置
uniqueKey或者用CollapseQueryParser去重,避免建议器返回重复结果。 - 你的
autocomplete字段设置了stored=true,如果不需要存储字段内容,可以改成stored=false,节省磁盘空间。
内容的提问来源于stack exchange,提问作者Samuel-Zacharie Faure

