突破性能瓶颈!ElasticSearch百亿级数据检索优化案例

突破性能瓶颈!ElasticSearch百亿级数据检索优化案例,第1张

本文中的数据平台已迭代三个版本,从头开始遇到很多常见的难题,终于有片段时间整理一些已完善的文档,在此分享以供所需朋友的。实现参考,少走些弯路,在此篇幅中偏重于ES的优化,目前生产已存储百亿数据,性能良好,关于HBase,Hadoop的设计优化估计有很多文章可以参考,不再赘述。

项目背景:在一业务系统中,部分表每天的数据量过亿,已按天分表,但业务上受限于按天查询,并且DB中只能保留3个月的数据(硬件高配),分库代价较高。

改进版本目标:

谈到优化必须能了解组件的基本原理,才容易找到瓶颈所在,以免走多种弯路,先从ES的基础结构说起(如下图):

一些基本概念:

ES依赖一个重要的组件Lucene,关于数据结构的优化通常来说是对Lucene的优化,它是集群的一个存储于检索工作单元,结构如下图:

在Lucene中,分为索引(录入)与检索(查询)两部分,索引部分包含 分词器、过滤器、字符映射器 等,检索部分包含 查询解析器 等。一个Lucene索引包含多个segments,一个segment包含多个文档,每个文档包含多个字段,每个字段经过分词后形成一个或多个term。

通过Luke工具查看ES的lucene文件如下,主要增加了_id 和 _source字段:

Lucene 索引文件结构主要的分为:词典、倒排表、正向文件、DocValues等,如下图:

Lucene 随机三次磁盘读取比较耗时。其中fdt文件保存数据值损耗空间大,tim和doc则需要SSD存储提高随机读写性能。
另外一个比较消耗性能的是打分流程,不需要则可屏蔽。

关于DocValues:

倒排索引解决从词快速检索到相应文档ID, 但如果需要对结果进行排序、分组、聚合等 *** 作的时候则需要根据文档ID快速找到对应的值。

通过倒排索引代价缺很高:需迭代索引里的每个词项并收集文档的列里面 token。这很慢而且难以扩展:随着词项和文档的数量增加,执行时间也会增加。Solr docs对此的解释如下:

在lucene 40版本前通过FieldCache,原理是通过按列逆转倒排表将(field value ->doc)映射变成(doc -> field value)映射,问题为逐步构建时间长并且消耗大量内存,容易造成OOM。

DocValues是一种列存储结构,能快速通过文档ID找到相关需要排序的字段。在ES中,默认开启所有(除了标记需analyzed的字符串字段)字段的doc values,如果不需要对此字段做任何排序等工作,则可关闭以减少资源消耗。

ES中一个索引由一个或多个lucene索引构成,一个lucene索引由一个或多个segment构成,其中segment是最小的检索域。

数据具体被存储到哪个分片上:shard = hash(routing) % number_of_primary_shards

默认情况下 routing参数是文档ID (murmurhash3),可通过 URL中的 _routing 参数指定数据分布在同一个分片中,index和search的时候都需要一致才能找到数据,如果能明确根据_routing进行数据分区,则可减少分片的检索工作,以提高性能。

在我们的案例中,查询字段都是固定的,不提供全文检索功能,这也是几十亿数据能秒级返回的一个大前提:

1、ES仅提供字段的检索,仅存储HBase的Rowkey不存储实际数据。
2、实际数据存储在HBase中,通过Rowkey查询,如下图。
3、提高索引与检索的性能建议,可参考官方文档(如 >在宿主机器编辑文件:vim /etc/docker/daemonjson

docker images 命令查看镜像列表

docker ps 命令查看es状态

浏览器输入 IP:9200

systemctl start docker

systemctl enable docker

systemctl stop docker

docker version

docker ps 查看任务
docker stop 容器id 停止容器
docker start 容器Id 启动容器
docker rm 容器Id 删除容器


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/10731218.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-10
下一篇 2023-05-10

发表评论

登录后才能评论

评论列表(0条)

保存