Solr 7.2.1批量索引50亿条HDFS数据报Socket超时该如何优化?
你的推测完全成立。批量写入过程中,Solr会不断生成小的索引段,后台的段合并线程会持续将小段合并成大段,这个过程会占用大量CPU、内存以及HDFS IO带宽,导致Solr节点无法及时响应Spark的写入请求,进而触发Socket超时、Broken pipe报错,同时索引耗时逐批上涨也是段合并资源占用持续累加的直接表现。
以下是针对性的解决方案:
一、合并策略核心优化(最高优先级)
你当前的TieredMergePolicy配置不合理,25的maxMergeAtOnce和segmentsPerTier会触发大量并行合并操作,资源开销极高:
- 调整为适合大批量离线索引的配置:
<mergePolicyFactory class="org.apache.solr.index.TieredMergePolicyFactory"> <!-- 降低单次合并的段数量,减少单次合并的资源开销 --> <int name="maxMergeAtOnce">10</int> <int name="segmentsPerTier">10</int> <!-- 离线索引阶段直接关闭复合文件,减少合并时的额外IO开销 --> <double name="noCFSRatio">0.0</double> <!-- 加大允许并发合并的线程数上限,提升合并效率,避免合并堆积 --> <int name="maxConcurrentMerges">6</int> </mergePolicyFactory>
- 升级合并调度器配置,提升合并效率:
<mergeScheduler class="org.apache.lucene.index.ConcurrentMergeScheduler"> <int name="maxThreadCount">6</int> <int name="maxMergeCount">9</int> </mergeScheduler>
- 如果业务允许索引完成后再对外提供查询,可在批量索引阶段关闭自动合并,所有数据写入完成后手动触发
forceMerge合并到1-2个大段,性能提升最明显。
二、超时问题临时修复
先解决当前任务直接失败的问题:
- 调整Spark-Solr客户端的超时参数,在提交任务时添加配置:
spark.solr.client.socketTimeout=600000、spark.solr.client.connectionTimeout=120000,把超时时间拉长到5-10分钟,避免正常的慢响应被判定为失败。 - 调整Solr服务端的Jetty超时配置,在
solr.in.sh中添加:SOLR_OPTS="$SOLR_OPTS -Dsolr.jetty.soTimeout=600000" - 调大Spark任务的重试次数,添加配置:
spark.task.maxFailures=10,允许单次写入失败后重试。
三、JVM与HDFS存储配置优化
- 你的Solr堆内存设置偏低,128G内存的节点可以把
SOLR_JAVA_MEM调整为-Xms60g -Xmx60g,MaxDirectMemorySize调整为30g,留出足够的内存给HDFS缓存和段合并操作。 - HDFS块缓存配置调整:把
solr.hdfs.blockcache.slab.count调整到4,扩大块缓存容量,减少合并时的磁盘IO开销。 - 关闭HDFS的不必要校验开销,添加配置:
<bool name="solr.hdfs.readshortcircuit">true</bool> <bool name="solr.hdfs.blockcache.write.enabled">false</bool>
四、索引流程优化
- 加大单次写入的批次大小,避免大量小请求压垮Solr:Spark端设置
spark.solr.batch.size=10000(根据单条记录大小调整,控制单批次大小在5-10MB即可)。 - 调整分批写入的节奏:每写入5000万条就暂停15-30分钟,等待后台合并完成后再写入下一批,避免写入和合并的资源抢占叠加。
- 调整集合分片配置:7个节点可以设置为14分片(每节点2分片),分散单分片的合并压力。
- 索引阶段关闭所有不需要的查询缓存、过滤器缓存,节省内存给合并操作:在solrconfig.xml中把所有cache类配置的size设为0。
五、其他优化点
- 离线索引阶段完全关闭软提交,所有数据写完后再手动打开:把
autoSoftCommit的maxTime设为-1。 - 升级spark-solr连接器到适配Solr7.2的最新版本,旧版本的重试逻辑存在缺陷,会把可重试的超时异常直接抛出导致任务失败。
- 索引阶段临时关闭Solr的副本写入,所有数据写入完成后再开启副本同步,减少写入阶段的IO开销。
内容的提问来源于stack exchange,提问作者gurdit sidhu
相关产品推荐
相关产品推荐

