极限压榨elasticsearch写入速度

标签: 极限 elasticsearch 速度 | 发表时间:2020-10-19 13:21 | 作者:小姐姐味道
出处:https://juejin.im/backend

不羡鸳鸯不羡仙,一行代码调半天。原创:小姐姐味道(微信公众号ID:xjjdog),欢迎分享,转载请保留出处。

ES使用非常广泛,尤其是ELKB,几乎是上点规模的日志系统,都在用它。

日志属于写多读少的业务场景,对写入速度要求很高。拿我们其中一个集群来说,单集群日志量达到百TB,每秒钟日志写入量达到 10W条。

ES不是单纯的顺序写,为了构造倒排索引,保证数据的可靠性和实时性,背后有很多耗时的merge或者额外操作,磁盘I/O和CPU的压力非常的大!

使用iotop去观测,可以发现ES的进程几乎占满了SSD磁盘的I/O资源,达到 200MB/s+。使用top命令观测,发现8核CPU的user几乎占满。ES是非常能吃资源的。

既然能很容易发现系统的瓶颈,那就着力去优化这个资源,极限压榨一下ES的写入速度。

本次优化的示例版本是 7.9.2。ES的版本升的是真快,已经完全脱离了5的时代了。

1、哪些操作占用资源

要进行优化,需要首先知道ES的写入过程,了解哪些步骤最耗时。

首先,就是副本(replica)问题,为了保证起码的高可用,这里的副本数量设置为1,是节省不了的。所以,将副本数量设置为0,只适合数据首次导入的时候。

如上图,一条数据想要最终落地,是需要经过多个步骤的。这个过程,甚至会有tranlog这样的备份机制。

ES的底层存储是Lucene,包含一系列的反向索引。这样的索引就成为 (segment)。但记录不会直接写入段,而是先写入一个缓冲区。

当缓冲区满了,或者在缓冲区呆的够久,达到了刷新时间(划重点),会一次性将缓冲区的内容写进段中。

这也是为什么 refresh_interval属性的配置会严重的影响性能。如果你不要很高的实时性,不妨将其配置的大一点。

缓冲区默认使用堆空间的10%,最小值为48mb(针对于分片的)。如果你的索引多且写入重,这部分内存的占用是可观的,可以适当加大。

2、开始优化

数据写入,主要有三个动作: flushrefreshmerge。通过调整它们的行为,即可在性能和数据可靠性之间进行权衡。

flush

从上面的介绍可以看出来, translog写入了一份全量的数据,它有点像MysSQL中的binlog,或者redis的aof,用来保证异常情况下的数据安全。

这是因为,我们把数据写到磁盘后,还要调用fsync才能把数据刷到磁盘中,如果不这样做在系统掉电的时候就会导致数据丢失。

ES默认每次请求都进行一次flush,但对于日志来说,这没有必要,可以将这个过程改为异步的,参数如下:

   curl -H "Content-Type: application/json"  -XPUT 'http://localhost:9200/_all/_settings?preserve_existing=true' -d '{
  "index.translog.durability" : "async",  
"index.translog.flush_threshold_size" : "512mb",
  "index.translog.sync_interval" : "60s"
}'
复制代码

这可以说是最重要的一步优化了,对性能的影响最大,但在极端情况下会有丢失部分数据的可能。对于日志系统来说,是可以忍受的。

refresh

除了写translog,ES还会将数据写入到一个缓冲区中。但是注意了!此时,缓冲区的内容是无法被搜索到的,它还需要写入到segment里面才可以。

这就是refresh动作,默认1秒。也就是你写入的数据,大概率1秒之后才会被搜索到。

所以ES并不是一个实时性的搜索系统,它是一个类实时系统(near-realtime)。

通过 index.refresh_interval可以修改这个刷新间隔。

对于日志系统来说,当然要把它调大一点啦。xjjdog这里调整到了120s,减少了这些落到segment的频率,速度自然会快。

   curl -H "Content-Type: application/json"  -XPUT 'http://localhost:9200/_all/_settings?preserve_existing=true' -d '{
  "index.refresh_interval" : "120s"
}'
复制代码

merge

merge其实是lucene的机制,它主要是合并小的segment块,生成更大的segment,来提高检索的速度。

原因就是refresh过程会生成一大堆小segment文件,数据删除也会产生空间碎片。所以merge,通俗来讲就像是碎片整理进程。像postgresql等,也有vaccum进程在干同样的事。

显而易见,这种整理操作,既让费I/O,又浪费CPU。

要命的是,merge有三种策略。

  • tiered 默认选项,它能合并大小相似的索引段,并考虑每层允许的索引段的最大个数。
  • log_byte_size 以字节数的对数为计算单位,选择多个索引来合并创建新索引。
  • log_doc 以索引段的文档数量为计算单位,选择多个索引来合并创建新索引。

每一种策略都有非常详细的针对性配置,在此不啰嗦。

由于日志系统并没有随机性的删除操作,所以我们保持默认就可以。

3、微调

新版本对线程池的配置进行了优化,不需要配置复杂的search、bulk、index线程池。有需要配置下面几个就行了:thread_pool.get.size, thread_pool.write.size, thread_pool.listener.size, thread_pool.analyze.size。具体可观测 _cat/thread_pool接口暴露的数据进行调整。

其实,可以通过配置多块磁盘的方式,来分散 I/O的压力,但容易会造成数据热点集中在单块磁盘上。

Lucene的索引建立过程,非常耗费CPU,可以减少倒排索引的数量来减少CPU的损耗。第一个优化就是减少字段的数量;第二个优化就是减少索引字段的数量。具体的操作,是将不需要搜索的字段,index属性设置为 not_analyzed或者 no。至于_source和_all,在实际调试中效果不大,不再赘述。

另外,如果日志是通过filebeat或者logstash这样的组件传导过来的,一般都是开启了批量模式。通过批量能够增加性能,但也不宜过大,可根据实际观测进行设置,一般1k-1w之间都是可以的。

End

ES有多种使用场景。鉴于它NoSQL的本质,有的甚至用它来替代传统的关系型数据库。

这是没有问题的,但要注意它的延迟。本文侧重的是吞吐量优先的日志写入场景,数据的延迟就尤为明显。ES默认不是为了这种场景设计的,所以开箱即用的配置就显得效率很低。

我们了解到ES写入有flush、refresh和merge过程。其中,对I/O影响最大的就是translog和merge的动作;对CPU影响最大的是索引创建和merge的过程。在平常的mapping设计中,要尽量减少字段的数量,以及索引字段的数量。如此双管齐下,才能把CPU和I/O两个瓶颈点给解决掉。

作者简介: 小姐姐味道 (xjjdog),一个不允许程序员走弯路的公众号。聚焦基础架构和Linux。十年架构,日百亿流量,与你探讨高并发世界,给你不一样的味道。

相关 [极限 elasticsearch 速度] 推荐:

极限压榨elasticsearch写入速度

- - 掘金后端
不羡鸳鸯不羡仙,一行代码调半天. 原创:小姐姐味道(微信公众号ID:xjjdog),欢迎分享,转载请保留出处. ES使用非常广泛,尤其是ELKB,几乎是上点规模的日志系统,都在用它. 日志属于写多读少的业务场景,对写入速度要求很高. 拿我们其中一个集群来说,单集群日志量达到百TB,每秒钟日志写入量达到 10W条.

elasticsearch 优化写入速度 | easyice

- -
translog flush 间隔调整. 索引刷新间隔调整: refresh_interval. bulk 线程池和队列大小. 调整字段 Mappings. 对于 Analyzed 的字段禁用 Norms. index_options 设置. 基于版本: 2.x – 5.x. 在 es 的默认设置,是综合考虑数据可靠性,搜索实时性,写入速度等因素的,当你离开默认设置,追求极致的写入速度时,很多是以牺牲可靠性和搜索实时性为代价的.有时候,业务上对两者要求并不高,反而对写入速度要求很高,例如在我的场景中,要求每秒200w 条的平均写入速度,每条500字节左右.

elasticsearch 写入速度提升的案例分享 - 独行侠梦 - 博客园

- -
文章首发投稿至InfoQ,【侠梦的开发笔记】公众号,欢迎关注. 基本配置,5台配置为 24C 125G 17T 的主机,每台主机上搭建了一个elasticsearch节点. 采用的elasticsearch集群版本为7.1.1. 管理工具包括kibana和cerebro. 数据来源为kafka的三个topic,主要用于实时日志数据的存储和检索,由于实时性要求,所以需要将数据快速的写入到es中.

iOS图片加载速度极限优化—FastImageCache解析

- - bang's blog
FastImageCache是Path团队开发的一个开源库,用于提升图片的加载和渲染速度,让基于图片的列表滑动起来更顺畅,来看看它是怎么做的. iOS从磁盘加载一张图片,使用UIImageVIew显示在屏幕上,需要经过以下步骤:. 从内核缓冲区复制数据到用户空间. 生成UIImageView,把图像数据赋值给UIImageView.

[译]elasticsearch mapping

- - an74520的专栏
es的mapping设置很关键,mapping设置不到位可能导致索引重建. 请看下面各个类型介绍^_^. 每一个JSON字段可以被映射到一个特定的核心类型. JSON本身已经为我们提供了一些输入,支持 string,  integer/ long,  float/ double,  boolean, and  null..

Elasticsearch as Database - taowen - SegmentFault

- -
【北京上地】滴滴出行基础平台部招聘 Elasticsearch 与 Mysql binlog databus 开发工程师. 内推简历投递给: [email protected]. 推销Elasticsearch. 时间序列数据库的秘密(1)—— 介绍. 时间序列数据库的秘密(2)——索引.

ElasticSearch 2 的节点调优(ElasticSearch性能)

- - 行业应用 - ITeye博客
一个ElasticSearch集群需要多少个节点很难用一种明确的方式回答,但是,我们可以将问题细化成一下几个,以便帮助我们更好的了解,如何去设计ElasticSearch节点的数目:. 打算建立多少索引,支持多少应用. elasticsearch版本: elasticsearch-2.x. 需要回答的问题远不止以上这些,但是第五个问题往往是容易被我们忽视的,因为单个ElasticSearch集群有能力支持多索引,也就能支持多个不同应用的使用.

Elasticsearch:使用 Elasticsearch 进行语义搜索

- - 掘金 后端
在数字时代,搜索引擎在通过浏览互联网上的大量可用信息来检索数据方面发挥着重要作用. 此方法涉及用户在搜索栏中输入特定术语或短语,期望搜索引擎返回与这些确切关键字匹配的结果. 虽然关键字搜索对于简化信息检索非常有价值,但它也有其局限性. 主要缺点之一在于它对词汇匹配的依赖. 关键字搜索将查询中的每个单词视为独立的实体,通常会导致结果可能与用户的意图不完全一致.

elasticsearch的javaAPI之query

- - CSDN博客云计算推荐文章
elasticsearch的javaAPI之query API. the Search API允许执行一个搜索查询,返回一个与查询匹配的结果(hits). 它可以在跨一个或多个index上执行, 或者一个或多个types. 查询可以使用提供的 query Java API 或filter Java API.

Elasticsearch基础教程

- - 开源软件 - ITeye博客
转自:http://blog.csdn.net/cnweike/article/details/33736429.     Elasticsearch有几个核心概念. 从一开始理解这些概念会对整个学习过程有莫大的帮助.     接近实时(NRT).         Elasticsearch是一个接近实时的搜索平台.