热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

6wes单个索引_Elasticsearch索引和检索优化与压测监控总结

1.Overview2.索引index-index优化项3.检索search-search优化项4.系统配置优化项5.压测esrally6.监控marvel7.注意事项8.Refe

add1c3ba8cf287898b3169f0adc2b5e7.png

1. Overview
2. 索引 index
- index优化项
3. 检索 search
- search优化项
4. 系统配置优化项
5. 压测 esrally
6. 监控 marvel
7. 注意事项
8. Reference
9. More
Overview

先来看看es的整体架构图,上面有多个重要模块,今天主要写在lucene上面的index模块与search模块的优化经历,力求简要写出改变了configuration之后,会给es cluster带来什么样的影响。

b9aa6033b27b7668088ad273b446f87c.png

Index Optimization

977e31d3d66b6e4aeb25e3392ef018ab.png

上图展示了一个doc index/write请求过来,es为其建立倒排的过程,而index opt.的优化点就主要集中在该posting list building过程,先认识4个组件(heap buff, os cache, transLog, disk),

  1. 客户端选择一个node发送请求过去,这个node就是coordinating node(默认master,data,ingest都是coord)

  2. coordinator对doc进行路由,将请求转发给对应的data node(有primary shard)

  3. 实际的node上的primary shard处理请求,然后将数据同步到replica node

  4. coordinator如果发现primary node和所有replica node都搞定之后,就返回响应结果给客户端

  5. 为了提高容错,doc双写

  • 写入es实例的heap buffer(此时doc未能被search)

  • 写入transLog(translog其实也是先写入os cache的,默认每隔5秒刷一次到磁盘中去,最多丢5秒的数据)

es实例在每个refresh interval里将heap里面的docs刷到Lucene利用着的系统缓存里(此时doc能够被search)

transLog根据配置的持久化到disk的策略,同步docs到磁盘(顺序写盘)

transLog的clean up

index优化项

  • mapping禁用不需要的功能

    • index,倒排索引,not_analyzed,注意是否分词,尽量精简schema字段个数,不会被检索的字段就不要建立倒排。.field("index", "no")

    • doc values,正排索引,用于聚合或者排序

    • norms,analyzed norms存储了多种正则化算子,用于docs的排序评分,如果不需要排序,可以disable norms

    • index_options,有docs(文档有无), freqs(重复出现的文档评分更高), positions(涵盖了前2种,并且多了位置信息,用于临近查询), offsets(全部,用于高亮)四类

  • 关闭_all,让查询匹配到具体schema,可以降低索引大小index.query.default_field:your_schema_replace_all, _all字段会给search带来方便,但是会增加index时间和index尺寸

  • indices.memory,es instance的memory buffer大小,buffer满了/一个refresh周期到了会刷到系统缓存,如果refresh足够大,buffer也足够大,与系统缓存的io次数会越小

    • The indexing buffer is used to store newly indexed documents it fills up

    • indices.memory.index_buffer_size defines the percentage of available heap memory that may be used for indexing operations

    • 新doc同时到es heap和transLog/WAL,即双写

  • index.translog.durability,request/async,translog的持久化策略,每个请求都flush/异步flush,flush持久化策略如下,

    • index.translog.flush_threshold_opts : 10000 (translog每个flush batch的条数)

    • index.translog.flush_threshold_size : 5000mb (flush batch size)

  • segment merge,每次refresh/flush都会产生段,lucene会将小段合并至大段,

    • indices/index.store.throttle.max_bytes_per_sec,限制段合并速度(indices节点级别,index索引级别)

    • index.merge.scheduler.max_thread_count,段合并线程数,机械硬盘建议设置为1,减少减少磁头争用

  • refresh_interval,es instance的memory buffer到系统缓存的时间间隔(检索实时性),一次es refresh会产生一个lucene segment;久刷新更能够利用缓存

  • number_of_replicas,首次索引设置为0,index过程中,如果有副本的话,doc也会马上同步到副本中去的,同时进行分词索引等,而index之后再传送就是传index后的内容了,不需要再经历分词索引部分。首次索引完成后再开启,以防node crash

    • provide high availability,stronger failover

    • scale out search volume/throughout since searches can be executed on all replicas in parallel(提高es的查询效率,es会自动在主或副本分片上对检索请求进行负载均衡,提前短路)

    • discovery.zen.minimum_master_nodes,如果replica完好,但是脑裂num设置不当,不幸裂开了2个cluster(clusterA与clusterB此时数据一致),此时对读的影响是不大的,但是对写就有问题,因为新写数据可能写在clusterA,也可能写在clusterB,那么下次查的时候就不一定能查到这条新写doc

  • number_of_shards,下面几条供参考,

    • 随着#shard变多,一个node可能有N个shard,node存在OOM风险

    • shard结果汇总到coordinator节点的时候,#shard * (from+size),coordinator存在OOM风险

    • #shard=(1.5~3) * #node

    • 索引分片数=数据总量/单分片容量(单个分片容量建议为20G~30G)

    • 索引分片数=数据总条数/单分片条数(单个分片的docs条数建议为5 million)

    • 有利于index性能,shard越多,bulk线程越多

    • 不利于search性能,因为search request会分发到每个routing shard

  • auto doc id,如果手动为es doc设置一个id,那么es在每个write req都要去确认那个id是否存在,这个过程是比较耗时的。而如果使用es的自动生成id,那么es就会跳过这个确认步骤,写入性能会更好。而对于业务中的表id/sku_id,可以将其作为es document的一个field。但是如果表id/sku_id不作为es doc id,在实时更新的时候会引入duplication,这时候就需要去重

  • 节点分离,master,data,ingest预处理节点,coordinator

  • disk storage,SSD固态硬盘,机械硬盘, es heavily uses disk(SSDs, RAID 0)

  • Spark入库时,Rdd的partition 的NodeClient一次操作基本会和大部分节点建立连接。建议事先根据shard规则(_id % shard_num/ routing_id % shard_num),将同一shard的数据事先都repartition到同一个partition。这样一个partition只要和一个Node建立连接。rdd.partitionBy(sku_id/cid3)

  • 分时段倾斜index线程(增加index线程数,那么search线程数就会减少,类似spark的dynamic memory)

    • thread pool,size=工作线程数,queue_size=pending队列长度

    • thread pool size for index/search/bulk

    • _cluster.threadpool.index.queue_size: 1000,index

    • _cluster.threadpool.search.queue_size: 100,search

  • index bulk request size,控制好写入批处理的每批大小

Search Optimization

8111d711780abb4620cef083bdae45ea.png

上图展示了一个query request过来,es对应的检索过程,默认是两阶段,首先是query过程,然后是fetch过程,

  1. 客户端选择一个node发送请求过去,这个node就是coordinating node

  2. coordinator node accept query search request(默认)

  3. coordinator根据请求的入参构造优先队列priority queue = (from+size)

  4. coordinator对routing/doc id进行哈希路由,将读请求转发到对应的node,此时req会在primary和replica shard中使用round-robin随机轮询算法,从而随机选择一个,让读请求负载均衡,并在每个shard构造(from+size)长的优先队列

  5. 每个shard执行lucene的倒排查找,然后进行逻辑或非与,计算排序分等,根据排序分将结果sortList(docId, score)写入本地队列中(局部有序)

  6. 每个shard将本地队列中的结果发送给coordinator

  7. coordinator接收所有routing shard的队列结果(接收的docs条数 = (from+size) * #shard,谨慎使用深分页,OOM),然后根据score进行全局排序,从from位置开始,挑选(from+size)条里面的size条,结束query阶段

  8. coordinator将size条docs的id发送到对应的shard,以请求该docId的其余字段信息sortList(docId, score, schema1, ..., schemaN)

  9. coordinator取到所有命中docId的详细信息后,返回response

search优化项

  • 设置routing

    • es会将相同routing的数据存放在同一个shard中。后续查询时,在指定routing之后,es只需要查询一个shard就能得到所有需要的数据,而不用去查询所有的shard,shard_num = hash(_routing) % num_primary_shards

    • 注意数据倾斜,如果routing的某个值的数据量太大,考虑更换routing_key为其他schema或者是多个schema的union

  • number_of_shards,同上

  • number_of_replicas,同上

  • filter clause,如果不需要lucene的score,使用filter语句而不用query语句

  • mapping的数据类型,选取最小的最合适,keyword, byte, short, integer, long, float, double

  • nested比parent-child更友善

  • 日期格式注意取舍精度,now -> now/m

  • max_num_segments,一个shard的最大segment数量,值越小,查询时所需打开的segment文件就越小,注意限速segment merge(动态写入更新的index推荐使用默认merge策略)

  • more file system cache,让系统内存尽可能容纳更多的Lucene索引段文件index segment file,那么搜索走内存的可能性就更大,与磁盘的io交互就越少

  • doc模型的简单化,使用es的基本term/query/agg功能,而复杂的join, nested, parent-child搜索尽量避免es来做,可以将结果取出来之后,在java/spark client里完成这些复杂聚合操作

  • 预先index data,对于一些常用的range查询,可以将range直接作为一个schema,这样可以直接使用term clause,而不需要走agg的range clause,即agg range price -> term price_range

  • 冷热数据分离, node级别的

    • node.attr.box_type: hot

    • index.routing.allocation.require.box_type: warm

  • 节点分离,master node与data node分离

    • node.master, handle search queries and only contact data nodes as needed

    • node.data, handle data related operations like CRUD, search, and aggregations

  • 清除删除文档,删除文档参与检索过程,但是返回是会过滤掉,所以如果清理了,就不会参与检索了. only_expunge_deletes = true

提高查询效率

  • 增加filesystem cache,操作系统会将磁盘文件里的数据自动缓存到 filesystem cache,这样查询会较少与disk的交互

  • 数据预热,如果filesystem cache不足放下所有数据,那么肯定有一部分要放在disk,此时可以开一个定时任务定时主动search hot data,让hot data能够长期驻留在filesystem cache

  • 冷热分离,将大量的访问很少、频率很低的冷数据,单独写一个索引,然后将访问很频繁的热数据单独写一个索引。这样可以确保热数据在被预热之后,尽量都让他们留在hot node的filesystem cache里,而不会被冷数据给冲刷掉

  • document模型设计(schema选取),es的关联、aggregation都是耗时操作,最好能在ETL入库es前就完成(比如说sum写成一个字段,而不是实时算sum)

  • document模型设计2,减少不必要的字段,例如body可以不存放在es内部,而存放在外部的hbase里面,通过doc_id来获取,而es只做倒排。这样可以减少es的data,以便更完全地存放于filesystem cache

  • 不要深分页,因为深分页需要算topK的,很容易拉爆coordinator节点。普遍情况是使用scroll_apisearch_after一页一页地拉取,而不是随机跳页

系统配置项

https://www.elastic.co/guide/en/elasticsearch/reference/5.6/system-config.html

  • heap size

  • GC(CMS, G1)

  • thread limits

  • disable swapping

  • 文件描述符

  • 虚拟内存

Stress Test

https://segmentfault.com/a/1190000011174694https://github.com/elastic/rally

使用esrally进行压测,对比优化前后es cluster的性能

  • track,压测用的数据集和测试策略(赛道)

  • car,不同配置的es实例(赛车)

  • race,以track与car为前提的一次压测(比赛)

  • tournament,多个race组成的一系列压测(系列赛)

  • pipeline,压测的步骤过程

799b258f5b57c14cc858ab49991fa4ae.png

e1bad2e92946db98cbb1a9e269d2c4ae.png

esrally --distribution-version=5.0.0 --track=geopoint --challenge=append-fast-with-conflicts --car="16gheap"

2debb8553cc948d65baf4c43d136f895.png

esrally list pipeline

Monitor

主要通过es的plugin来监控_cat api的metrics,

  • kibana

  • marvel

  • kopf/cerebro

  • head

使用marvel查看对应的性能指标,

  • search rate

  • search latency

  • indexing rate

  • indexing latency

  • index size

  • dos count

  • fielddata size

  • lucene memory

  • segment count

  • JVM heap usage

  • cpu utilization

  • system load, etc.

75dc44e66250f514d6e0498765fea42c.png

1de49192ca460b8feb20bed97a532feb.png

注意事项

elasticsearch的版本迭代快,在实际部署使用前,最好阅读一遍对应版本的document,并了解其相应configuration。


Reference
  • How to Maximize Elasticsearch Indexing Performance

  • Anatomy of an Elasticsearch Cluster

  • Tune for indexing speed

  • Tune for search speed

  • Elasticsearch: The Definitive Guide

  • 将 ELASTICSEARCH 写入速度优化到极限

  • ES搜索性能优化


More
  • Elasticsearch - Performance Tuning

——END——2eeeb6760c24dbaa09894bf8144b746c.png

文章不错?点个【在看】吧! ?




推荐阅读
  • 在Android应用开发中,实现与MySQL数据库的连接是一项重要的技术任务。本文详细介绍了Android连接MySQL数据库的操作流程和技术要点。首先,Android平台提供了SQLiteOpenHelper类作为数据库辅助工具,用于创建或打开数据库。开发者可以通过继承并扩展该类,实现对数据库的初始化和版本管理。此外,文章还探讨了使用第三方库如Retrofit或Volley进行网络请求,以及如何通过JSON格式交换数据,确保与MySQL服务器的高效通信。 ... [详细]
  • Android 构建基础流程详解
    Android 构建基础流程详解 ... [详细]
  • 在探讨如何在Android的TextView中实现多彩文字与多样化字体效果时,本文提供了一种不依赖HTML技术的解决方案。通过使用SpannableString和相关的Span类,开发者可以轻松地为文本添加丰富的样式和颜色,从而提升用户体验。文章详细介绍了实现过程中的关键步骤和技术细节,帮助开发者快速掌握这一技巧。 ... [详细]
  • 为了在Hadoop 2.7.2中实现对Snappy压缩和解压功能的原生支持,本文详细介绍了如何重新编译Hadoop源代码,并优化其Native编译过程。通过这一优化,可以显著提升数据处理的效率和性能。此外,还探讨了编译过程中可能遇到的问题及其解决方案,为用户提供了一套完整的操作指南。 ... [详细]
  • 本文探讨了如何利用Java代码获取当前本地操作系统中正在运行的进程列表及其详细信息。通过引入必要的包和类,开发者可以轻松地实现这一功能,为系统监控和管理提供有力支持。示例代码展示了具体实现方法,适用于需要了解系统进程状态的开发人员。 ... [详细]
  • 2018 HDU 多校联合第五场 G题:Glad You Game(线段树优化解法)
    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6356在《Glad You Game》中,Steve 面临一个复杂的区间操作问题。该题可以通过线段树进行高效优化。具体来说,线段树能够快速处理区间更新和查询操作,从而大大提高了算法的效率。本文详细介绍了线段树的构建和维护方法,并给出了具体的代码实现,帮助读者更好地理解和应用这一数据结构。 ... [详细]
  • 【系统架构师精讲】(16):操作系统核心概念——寄存器、内存与缓存机制详解
    在计算机系统架构中,中央处理器(CPU)内部集成了多种高速存储组件,用于临时存储指令、数据和地址。这些组件包括指令寄存器(IR)、程序计数器(PC)和累加器(ACC)。寄存器作为集成电路中的关键存储单元,由触发器构成,具备极高的读写速度,使得数据传输非常迅速。根据功能不同,寄存器可分为基本寄存器和移位寄存器,各自在数据处理中发挥重要作用。此外,寄存器与内存和缓存机制的协同工作,确保了系统的高效运行。 ... [详细]
  • 在Java分层设计模式中,典型的三层架构(3-tier application)将业务应用细分为表现层(UI)、业务逻辑层(BLL)和数据访问层(DAL)。这种分层结构不仅有助于提高代码的可维护性和可扩展性,还能有效分离关注点,使各层职责更加明确。通过合理的设计和实现,三层架构能够显著提升系统的整体性能和稳定性。 ... [详细]
  • Android中将独立SO库封装进JAR包并实现SO库的加载与调用
    在Android开发中,将独立的SO库封装进JAR包并实现其加载与调用是一个常见的需求。本文详细介绍了如何将SO库嵌入到JAR包中,并确保在外部应用调用该JAR包时能够正确加载和使用这些SO库。通过这种方式,开发者可以更方便地管理和分发包含原生代码的库文件,提高开发效率和代码复用性。文章还探讨了常见的问题及其解决方案,帮助开发者避免在实际应用中遇到的坑。 ... [详细]
  • 本文介绍了如何在iOS平台上使用GLSL着色器将YV12格式的视频帧数据转换为RGB格式,并展示了转换后的图像效果。通过详细的技术实现步骤和代码示例,读者可以轻松掌握这一过程,适用于需要进行视频处理的应用开发。 ... [详细]
  • Netty框架中运用Protobuf实现高效通信协议
    在Netty框架中,通过引入Protobuf来实现高效的通信协议。为了使用Protobuf,需要先准备好环境,包括下载并安装Protobuf的代码生成器`protoc`以及相应的源码包。具体资源可从官方下载页面获取,确保版本兼容性以充分发挥其性能优势。此外,配置好开发环境后,可以通过定义`.proto`文件来自动生成Java类,从而简化数据序列化和反序列化的操作,提高通信效率。 ... [详细]
  • 本文深入解析了 FCEUX 源码,并详细介绍了两种制作 DEB 包的方法及其技术细节。首先,DEB 包通常由两部分组成:控制信息(位于 DEBIAN 目录)和安装内容(模拟目录)。通过解压现有的 DEB 包,可以查看其内部结构,进而理解其工作原理。具体操作包括将安装内容释放到指定目录中,以便进行进一步的修改和定制。此外,文章还探讨了如何修改现有的 DEB 包,以满足特定需求,提供了实用的步骤和技巧。 ... [详细]
  • CentOS 7环境下Jenkins的安装与前后端应用部署详解
    CentOS 7环境下Jenkins的安装与前后端应用部署详解 ... [详细]
  • 在过去,我曾使用过自建MySQL服务器中的MyISAM和InnoDB存储引擎(也曾尝试过Memory引擎)。今年初,我开始转向阿里云的关系型数据库服务,并深入研究了其高效的压缩存储引擎TokuDB。TokuDB在数据压缩和处理大规模数据集方面表现出色,显著提升了存储效率和查询性能。通过实际应用,我发现TokuDB不仅能够有效减少存储成本,还能显著提高数据处理速度,特别适用于高并发和大数据量的场景。 ... [详细]
  • 揭秘腾讯云CynosDB计算层设计优化背后的不为人知的故事与技术细节
    揭秘腾讯云CynosDB计算层设计优化背后的不为人知的故事与技术细节 ... [详细]
author-avatar
我有岁月619
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有