`
mozhenghua
  • 浏览: 324578 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

合理设置Solr Schema防止出现OOM

    博客分类:
  • solr
 
阅读更多

背景:

      晚上收到报警,说线上的一个solr的collection挂掉了,赶紧打开远程服务起查看服务器的状态,果然业务方查询全部超时,增量更新也宕机了,从异常信息上来看是集群中没有可用的节点可以使用,看到这样的问题,第一想到的是要重启一下服务器。悲剧的是重启完服务器,服务只正常了15秒钟,转而又全部宕机。

     

      判断是VM的堆内存溢出了,看了一下虚拟机启动参数 -Xmx4400m -Xms4400m(服务器是8G内存)

,临时的解决方案是增加内存,设置为-Xmx6400m -Xms6400m,设置完成,迅速重启服务器之后,观察了一会,core节点果然是不会挂了,但,通过命令工具 jstat -gcutil 命令查看VM fullgc的状态,观察到Full GC的频率是比较高,只是服务器勉强不会挂罢了。

     

     同事告诉我他们团队刚刚上了一个新的查询需求,这个提示我是不是因为的查询里面设置了什么查询条件的原因,随即仔细查看了一下日志,果然在查询日志中观察到了有两个查询中带sort的参数,需要排序的字段在在schema field节点只是设置了indexed=true而没有设置docValues=true ,瞬间明白了为什么会OOM。

 

原因分析:

      究其原因是客户端查询请求中需要sort的字段在schema field定义中,开启了indexed=true ,但是没有开启docValue=true,这样solr在对命中结果集进行排序时候,会将docid对应的value预先加载内存中,如果一个core中文档数有2000w条的话,试想一个long字段类型的field,在内存中就需要2000w*8个字节的内存,大概152兆内存,而且这个内存块需要随着文档内容更新,频繁刷新,内存频繁OOM也可想而知了。

     在solr5.0开始,框架中引入了docvalue机制,按照我现在的理解,这种存贮格式有以下三个特点:

  1. 这始终列存储,所以通过docid取单列中的内容比基于行存储的document中的内容要要快上好多倍
  2. 存储中的内容在物理上是按序排列的,利用这个特性,在文档排序时,只需要通过docid取对应的所在存储上的偏移量offset,通过这个offset偏移量就能判断两个值的大小,这样就能省去额外的IO开销,具体可以查看org.apache.solr.response.SortingResponseWriter这个类。基于此,solr框架可以衍生出很多非常酷的功能,比如基于"/export"的流式导出功能,和基于"/export"的stream expression功能。
  3. 存储内容不是依赖于内存的,这个和老版本的fieldcache机制有本质区别。

以下是查询中使用了sort字段,solr的执行栈路径视图:


 从调用路径来看,最终会调用FieldCacheImpl的getNumerics的方法,如下:

@Override
  public NumericDocValues getNumerics(LeafReader reader, String field, Parser parser, boolean setDocsWithField) throws IOException {
    if (parser == null) {
      throw new NullPointerException();
    }
    // schema field 上是否开启了docValue=true
    final NumericDocValues valuesIn = reader.getNumericDocValues(field);
    if (valuesIn != null) {
      // Not cached here by FieldCacheImpl (cached instead
      // per-thread by SegmentReader):
      return valuesIn;
    } else {
      final FieldInfo info = reader.getFieldInfos().fieldInfo(field);
      if (info == null) {
        return DocValues.emptyNumeric();
      } else if (info.getDocValuesType() != DocValuesType.NONE) {
        throw new IllegalStateException("Type mismatch: " + field + " was indexed as " + info.getDocValuesType());
      } else if (info.getIndexOptions() == IndexOptions.NONE) {
        return DocValues.emptyNumeric();
      }
      return (NumericDocValues) caches.get(Long.TYPE).get(reader, new CacheKey(field, parser), setDocsWithField);
    }
  }
 

 

通过代码了解到,先调用LeafReader的getNumericDocValues的方法,结果是否为空取决于schema中的field定义是否设置docValue=true设置,如果开启了docvalue这里就能直接取得docValue对象,不然的话就通过预先在cache中准备的五种基于索引term的,field加载策略:

 

  private Map<Class<?>,Cache> caches;
  FieldCacheImpl() {
    init();
  }
  private synchronized void init() {
    caches = new HashMap<>(6);
    caches.put(Long.TYPE, new LongCache(this));
    caches.put(BinaryDocValues.class, new BinaryDocValuesCache(this));
    caches.put(SortedDocValues.class, new SortedDocValuesCache(this));
    caches.put(DocTermOrds.class, new DocTermOrdsCache(this));
    caches.put(DocsWithFieldCache.class, new DocsWithFieldCache(this));
  }
    我就纳闷了,solr5.0中既然已经有docvalue机制,为什么还要在框架中保留这些通过term预加载到内存的fieldcache机制,因为一旦用户需要使用排序,功能而又在schema中忘记定义docvalue为true,一旦文档数量多,很有可能导致OOM的,也许solr的开发者为了版本向下兼容的原因吧。

 

    问题解决:

     那如何解决用户索引结构不当使用导致的OOM问题呢,是通过在wiki中标注,应该如何小心的配置schema,来防止出现类似的问题。这就像在市区的马路上,通过在马路当中画上双黄线,来明令告知驾驶者不要越过双黄线逆向行驶,但事实是在高峰期,只要没有监控的地方总有胆子大的驾驶者要越过双黄线,解决办法就是,要像高速公路上在马路中间建造隔离带,强行防止开到逆向车道上去,但是这个成本确实是有点高,但是非常有效。我们在做平台式的产品中也需要借鉴类似经验,需要在平台产品中构筑起一个个轨道,保证用户在既定的轨道上操作,如果用户试图跳出既定轨道,我们就要通过友好的反馈消息告知他已经偏离了轨道需要及时纠正。这样一种办法,可定比在wiki中写开发规约之类的东西有效,友好得多。

 

    所以我在solr容器启动的时,执行了一个将solr框架预先准备的cache清空的操作,后续如果有操作试图不通过docvalue机制来执行sort之类的操作就一律报错,这样在开发过程中就避免的因为不合理设置schema导致的错误,代码如下:

   RemoveFieldCacheListener:

 

public class RemoveFieldCacheListener implements ServletContextListener {

	@Override
	public void contextInitialized(ServletContextEvent sce) {
		RemoveFieldCacheStrategy.removeFieldCache();
	}
	@Override
	public void contextDestroyed(ServletContextEvent sce) {
	}
}
 RemoveFieldCacheStrategy:

 

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.Map;

import org.apache.lucene.index.BinaryDocValues;
import org.apache.lucene.index.LeafReader;
import org.apache.lucene.index.SortedDocValues;
import org.apache.lucene.uninverting.FieldCacheImpl.Cache;
import org.apache.lucene.uninverting.FieldCacheImpl.CacheKey;
import org.apache.lucene.uninverting.FieldCacheImpl.DocsWithFieldCache;
import org.apache.lucene.util.Accountable;

public class RemoveFieldCacheStrategy {

	@SuppressWarnings("all")
	public static void removeFieldCache() {
		try {
			FieldCacheImpl fieldCacheManager = (FieldCacheImpl) FieldCache.DEFAULT;
			Field cacheField = FieldCacheImpl.class.getDeclaredField("caches");
			cacheField.setAccessible(true);
			// 防止启动的时候在schema中没有设置 docvalue属性的时候,字段设置了indexed=true
			// 将doc的term的值预先加载到内存中,防止業務方不適當設置query對象導致服務端oom
			Map<Class<?>, Cache> caches = (Map<Class<?>, Cache>) cacheField.get(fieldCacheManager);

			FieldCacheImpl.Cache disable = new FieldCacheImpl.Cache(null) {
				@Override
				public Object get(LeafReader reader, CacheKey key, boolean setDocsWithField)
						throws IOException {
					throw new IllegalStateException(
							"you are intending to use sorting,facet,group or other statistic feature,please set field:["
									+ key.field + "] docValue property 'true'");
				}
				@Override
				protected Accountable createValue(LeafReader reader, CacheKey key,
						boolean setDocsWithField) throws IOException {
					return null;
				}
			};
			caches.clear();
			caches.put(Long.TYPE, disable);
			caches.put(BinaryDocValues.class, disable);
			caches.put(SortedDocValues.class, disable);
			caches.put(DocTermOrds.class, disable);
			caches.put(DocsWithFieldCache.class, disable);

		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
}

 完!

 

   

      

 

 

  • 大小: 58.1 KB
分享到:
评论

相关推荐

    solr schema solrconfig 配置文件解析

    Solr,作为一款开源的全文搜索引擎,其核心配置文件包括`schema.xml`和`solrconfig.xml`,它们是Solr工作方式的基础。在深入理解这两个文件之前,我们需要先了解Solr的基本架构。 **1. Solr架构简介** Solr采用...

    solrconfig.xml和schema.xml说明

    ### Solrconfig.xml 和 Schema.xml 说明 #### Solrconfig.xml 概述 Solrconfig.xml 是 Apache Solr 的核心配置文件之一,主要用于定义 Solr 实例...理解并合理配置这些选项对于充分发挥 Solr 的性能是非常重要的。

    快速上手数据挖掘之solr搜索引擎高级教程(Solr集群、KI分词)第02讲 solr5之Schema 共10页.pptx

    【课程大纲】第01讲 solr5简介第02讲 solr5之Schema第03讲 solr5之Solrconfig第04讲 solr5单机安装与配置第05讲 solrj基础(一)第06讲 solrj基础(二)第07讲 solrj之SolrBean第08讲 solrj语法详解第09讲 Solrj之...

    解决solr启动404问题

    当你在尝试启动Solr时遇到404错误,这通常意味着Solr服务没有正确地启动或者配置文件设置不正确。404错误表示“未找到”,在Web服务器中通常意味着请求的资源无法被定位。下面我们将深入探讨如何解决这个问题。 ...

    Apache Solr(solr-8.11.1.tgz)

    它包括一个默认的配置集,以及一个简单的数据导入处理程序(DIH)示例,帮助开发者了解如何设置和使用Solr。 5. **docs 目录**:包含了Solr的文档,包括用户手册、API参考和教程,对于学习和调试Solr非常有用。 6....

    solr深入浅出

    这涉及到Schema设计(如哪些字段应被索引,哪些应被存储),配置优化(mergeFactor、缓存设置等),内存管理(防止内存溢出,合理分配JVM内存),以及更新频率和查询响应压缩等方面的权衡。 总的来说,掌握Solr的...

    solr服务器_solr_

    合理的Schema设计是确保Solr性能的关键。 5. **请求处理器(Request Handler)**:Solr通过Request Handler来处理HTTP请求,如搜索、添加、删除和更新文档。常见的Request Handler有`/select`(用于搜索)、`/...

    SOLR的应用教程

    Schema是Solr的核心配置之一,用于定义索引字段、数据类型、分析器等,它允许用户自定义字段的属性,以满足不同数据的处理需求。 1.2.3 查询 Solr提供丰富的查询语法,包括布尔运算、短语匹配、范围查询等,还支持...

    solr(solr-9.0.0.tgz)

    5. **example** 文件夹:提供了一个简单的Solr实例,包括了如何设置和运行的基本示例,对于初学者来说非常有用。 6. **contrib** 文件夹:这个目录包含了一些社区贡献的模块,它们可能提供了额外的功能或者对Solr的...

    Apache Solr(solr-8.11.1.zip)

    Apache Solr是一款开源的企业级搜索平台,由Apache软件基金会维护。它是基于Java的,提供了高效、可扩展的全文检索、数据分析和分布式搜索功能。Solr-8.11.1是该软件的一个特定版本,包含了从早期版本到8.11.1的所有...

    solr4.7服务搭建

    1. **修改 schema.xml 文件**:打开 `D:\solr\home` 目录下的 schema.xml 文件,增加或修改以下字段类型定义: ```xml &lt;fieldType name="textComplex" class="solr.TextField" positionIncrementGap="100"&gt; ...

    solr7.2.1 ik

    2. **配置Solr Schema**:在Solr的Schema.xml文件中,需要为需要分词的字段指定`&lt;analyzer&gt;`标签,并在其中使用IK分词器。例如: ```xml &lt;fieldType name="text_ik" class="solr.TextField" positionIncrementGap=...

    solrcore 添加修改控制

    当某个节点上的SolrCore出现问题时,集群应能自动将请求路由到其他健康的节点,保证服务的连续性。 10. **版本控制** 使用版本控制系统(如Git)管理SolrCore的配置文件,可以帮助跟踪改动历史,便于回滚到之前的...

    ikanalyzer-solr8.4.0_solr8_solr_ikanalyzer_中文分词_

    ikanalyzer 是一个专门为Java开发的中文...总之,ikanalyzer-solr8.4.0 是 Solr 8.4.0 版本下用于中文分词的重要工具,通过合理的配置和使用,可以显著提高 Solr 对中文文本的处理能力,从而提升搜索质量和用户体验。

    solr-4.4.0.tgz

    - 根据系统负载和性能需求,调整 Solr 的配置参数,例如增加索引段大小、调整缓存设置等。 以上就是 Solr 4.4.0 版本的主要知识点,以及如何在 Linux 环境下进行安装和部署到 Tomcat。通过熟练掌握这些步骤,你将...

    docker配置solr登录密码文件

    docker配置solr登录密码文件,内含配置密码的文件 、web.xml的文件 ,详情可以去看我的博客,博客地址:https://blog.csdn.net/huyande123/article/details/97110784

    solr4.4部署、维护、调优

    接着,我们需要修改 Solr 的 `schema.xml` 文件,添加一个新的字段类型,指定使用 IKAnalyzer 进行中文分词。完成这些修改后,重启 Tomcat 使更改生效。 在维护 Solr 时,可能需要进行一些性能优化。对于 Tomcat,...

    最新版windows solr-8.8.2.zip

    4. **Schema设计**:Solr使用Schema.xml文件来定义索引字段,包括字段类型、分词器、过滤器等,这对于优化搜索性能至关重要。 5. **RESTful API**:Solr 8.8.2支持JSON、XML等多种格式的HTTP接口,便于通过编程方式...

    ikanalyzer-solr中文分词包兼容solr7.5

    在Solr的Schema设计中,可以为需要分词的字段指定`ikanalyzer`作为分析器,这样在索引和查询时,Solr就会使用ikanalyzer进行分词操作。 总之,ikanalyzer-solr中文分词包为Solr提供了一种强大的中文处理能力,使得...

    solr6 增量导入demo

    2. 配置Solr schema:确保Solr的Schema.xml文件包含了需要索引的所有字段,包括用于增量检测的字段。 3. 启用DeltaImport:在Solr的请求处理器中启用DeltaImport,以便能够通过HTTP请求触发增量导入。 四、定时...

Global site tag (gtag.js) - Google Analytics