Hadoop大数据实战

内容中心基于elasticsearch快速搭建搜索引擎

2019-04-11  本文已影响304人  郭彦超

一、背景

易企秀创意云矩阵下面运营了多个以内容发布为核心的互联网产品,每天都有大量企业与设计师在这些平台制作并传播他们的作品,每个产品又由不同部门及技术小组分管运营,底层的技术框架、存储以及数据结构差异性都比较大,产品要求整合各产品线数据做一个一站式搜索引擎,数据要求尽可能与业务线保持实时同步,并且允许用户对搜索结果按照实时阅读量进行排序。幸运的是,elasticsearch提供了丰富的功能帮我们实现了大部分的操作,大幅降低了系统的维护成本。

二、数据处理流程

业务线用到的数据库主要有3类,分别是MySQL、oracle、MongoDB,其中内容数据存储在MongoDB中,其它基础信息分别储存在MySQL与oracle中,如标题、作者、发布时间等信息。那么对应的数据处理流程包含:数据抽取>数据清洗>映射到es>提供query。

三、配置与优化

结合上述业务场景,如果不做任何优化,首次检索大约1s左右才能响应;由于es内部会对query和segment做缓存,当相似条件多次请求后,平均响应时间会降到500ms左右;经过对数据库、索引配置、查询语句三个层面简单配置后,首次检索降到了200ms以内,平均响应时间降了一个量级。

elasticsearch为满足多种不同的应用场景,底层提供多种数据结构支持,并做了大量的默认配置优化,部分配置针对具体的用户使用场景可能是冗余的,甚至可能造成性能的下降,需要根据实际业务场景做适当取舍,我们结合自身使用场景做了如下优化(文章中有疏漏或不正确的地方也欢迎点评指正):

数据库

1、jvm内存,分配给es的内存不要超出系统内存的50%,预留一半给Lucene,因为Lucene会缓存segment数据提升检索性能;内存配置不要超过32g,如果你的服务器内存没有远远超过64g,那么不建议将es的jvm内存设置为32g,因为超过32g后每个jvm对象指针的长度会翻倍,导致内存与cpu的开销增大。
2、禁用swapping,开启服务器虚拟内存交换功能会对es产生致命的打击,如果某个segment数据被缓存到了磁盘上,会导致原来0.1毫秒的操作变成10毫秒,大大降低数据的检索性能,使得es在提供查询服务时出现木桶效应,拖跨整个集群的对外服务性能。
3、硬盘配置,建议使用SSD,如果你的服务器硬盘是一块200g的机械硬盘,那么建议分成两块100g的盘去使用,这样能大大提升es读写硬盘的能力,通过elasticsearch.yml中的path.data来实现。
4、其它配置

bootstrap.memory_lock: true
#设置为true锁住内存,当服务混合部署了多个组件及服务时,应开启此操作,允许es占用足够多的内存。
indices.breaker.request.limit: 10%
#设置单个request请求的内存熔断限制,默认是jvm堆的60%(es7.0引入了新的内存熔断机制,会智能判断,规避OOM)。
index.merge.scheduler.max_thread_count: 1
#设置segment合并时占用的线程数,配置线程数越多对磁盘io消耗就越大(SSD忽略)。
indices.queries.cache.size:20%
#query请求可使用的jvm内存限制,默认是10%。
indices.requests.cache.size:2%
#查询request请求的DSL语句缓存,被缓存的DSL语句下次请求时不会被二次解析,可提升检索性能,默认值是1%。
indices.fielddata.cache.size:30%
#设置字段缓存的最大值,默认无限制。

索引配置

1、通过配置index_options优化text field的索引生成方式,es默认除生成倒排以外还会记录文档的词频与term的位置信息,如果只是用来对文档的检索不需要评分与高亮,可优化。

2、禁用field评分,如果该字段不需参与相关度打分那么可禁用,通过将norms设置为false来禁用评分提升检索性能。

3、Number类型的优化,如果该数字类型字段存储的是type信息 ,不会进行排序与范围查询操作,建议存储为keyword类型,keyword本身做了大量优化操作,对于检索与过滤性能更佳。

4、禁用doc_values,es为提升keyword类型下数据的排序与聚合性能,默认为每一个keyword field都开启了此功能,非必要场景禁用此操作可节省磁盘空间。

5、开启最优化压缩,通过配置"index.codec":"best_compression"开启最优压缩,可节省磁盘空间,但会增大cpu负载。

6、设置合适的分片数,多分片为es集群提供了分布式计算的保障,但一般不建议超过服务器的数量,过多的分片就意味着会有过多的segment产生,过多的segment消耗内存与系统IO。

7、设置合适的副本数,虽然多副本可以提升es的并发处理能力,但根据实际应用当中,这个值不建议配置太高,因为副本数据在进行同步时会带来过高的IO消耗。

8、降低刷新操作,过高的刷新会增大磁盘io负载,通过配置"index.refresh_interval":"-1"来控制刷新频率,es默认配置为1s,如果对数据时效性要求不高的话修改为30s-60s,-1表示禁用刷新。

9、通过forcemerge 强制合并索引段,定期清理过小的segment段,Lucene为加快检索速度,会为每个segment构建一层FST前缀索引,这些数据会全部加载到内存,降低segment段的数量有助于降低内存的消耗,过多的segment段也会增大底层os打开关闭文件的时间。

10、copy_to,使用multi_match在大数据量场景下进行多字段查询会很慢,利用copy_to将多个字段中的索引合并到一个字段,使用match查询该字段性能大幅提升。

查询优化

1、尽量避免深度翻页场景,默认最大结果集深度为10000,可根据实际使用场景适当调大该值,如index.max_result_window:20000 ,该值设置过大,在高并发场景下会频繁触发es内部gc操作,影响整体性能。

2、使用sliced scroll翻页拉取大数据结果集,大家都知道使用scroll去做深度翻页读取大量数据,但这种操作不支持online,原因就是它的指针是全局的无法支撑高并发操作,这时需要用到sliced scroll。

3、尽可的使用filter操作,因为filter操作会使用缓存并且不会进行评分计算,性能高于query。

4、如果查询语句比较复杂且不需要翻页操作的话可增加timeout=1s&terminate_after=10000两个参数,在高并发场景下性能提升3-5倍。

四、小结

5个实例(8核16g)索引了上亿文档内容,优化后任意检索一条数据由原来的1s左右降低到200ms内 ,平均性能提升3-5倍。

上一篇 下一篇

猜你喜欢

热点阅读