当前位置:  首页 数码 详情

我们将ES索引的写入性能翻倍,我们下线了超过400台物理机

发布来源:互联网    发布时间:2020-09-27 20:57

我们将ES索引的写入性能翻倍,我们下线了超过400台物理机(图1)

魏子珺,滴滴专家工程师。滴滴Elasticsearch引擎负责人,负责带领引擎团队深入Elasticsearch内核,解决在海量规模下Elasticsearch遇到的稳定性、性能、成本方面的问题。曾在、工作,有丰富的引擎建设经验。

滴滴ElasticSearch平台承接了公司内部所有使用ElasticSearch的业务,包括核心搜索、RDS从库、日志检索、安全数据分析、指标数据分析等等。平台规模达到了3000+节点,5PB 的数据存储,超过万亿条数据。平台写入的峰值写入TPS达到了2000w/s,每天近 10 亿次检索查询。为了承接这么大的体量和丰富的使用场景,滴滴ElasticSearch需要解决稳定性、易用性、性能、成本等诸多问题。我们在4年多的时间里,做了大量优化,积攒了非常丰富的经验。通过建设滴滴搜索平台,打造滴滴ES引擎,全方位提升用户使用ElasticSearch体验。这次给大家的是滴滴在写入性能优化的实践,优化后,我们将ES索引的写入性能翻倍,结合数据冷热分离场景,支持大规格存储的物理机,给公司每年节省千万左右的成本。

一、背景

前段时间,为了降低用户使用ElasticSearch的存储成本,我们做了数据的冷热分离。为了保持集群磁盘利用率不变,我们减少了热节点数量。ElasticSearch集群开始出现写入瓶颈,节点产生大量的写入rejected,大量从kafka同步的数据出现写入延迟。我们深入分析写入瓶颈,找到了突破点,最终将Elasticsearch的写入性能提升一倍以上,解决了ElasticSearch瓶颈导致的写入延迟。这篇文章介绍了我们是如何发现写入瓶颈,并对瓶颈进行深入分析,最终进行了创新性优化,极大的提升了写入性能。

二、写入瓶颈分析

1、发现瓶颈

我们去分析这些延迟问题的时候,发现了一些不太好解释的现象。之前做性能时,ES节点cpu利用率能超过80%,而生产环境延迟索引所在的节点cpu资源只使用了不到50%,集群平均cpu利用率不到40%,这时候IO和网络带宽也没有压力。通过提升写入资源,写入速度基本没增加。于是我们开始一探究竟,我们选取了一个索引进行验证,该索引使用10个ES节点。从下图看到,写入速度不到20w/s,10个ES节点的cpu,峰值在40-50%之间。

我们将ES索引的写入性能翻倍,我们下线了超过400台物理机(图2)

为了确认客户端资源是足够的,在客户端不做任何调整的情况下,将索引从10个节点,扩容到16个节点,从下图看到,写入速度来到了30w/s左右。

这证明了瓶颈出在服务端,ES节点扩容后,性能提升,说明10个节点写入已经达到瓶颈。但是上图可以看到,CPU最多只到了50%,而且此时IO也没达到瓶颈。

2、 ES写入模型说明

这里要先对ES写入模型进行说明,下面分析原因会跟写入模型有关。

我们将ES索引的写入性能翻倍,我们下线了超过400台物理机(图3)

客户端一般是准备好一批数据写入ES,这样能极大减少写入请求的网络交互,使用的是ES的BULK接口,请求名为BulkRequest。这样一批数据写入ES的ClientNode。ClientNode对这一批数据按数据中的routing值进行分发,组装成一批BulkShardRequest请求,发送给每个shard所在的DataNode。发送BulkShardRequest请求是异步的,但是BulkRequest请求需要等待全部BulkShardRequest响应后,再返回客户端。

3、 寻找原因

我们在ES ClientNode上有记录BulkRequest写入slowlog。

`items`是一个BulkRequest的发送请求数。

`totalMills `是BulkRequest请求的耗时。

`max`记录的是耗时最长的BulkShardRequest请求。

`avg`记录的是所有BulkShardRequest请求的平均耗时。

我这里截取了部分示例。

从示例中可以看到,2条记录的avg相比max都小了很多。一个BulkRequest请求的耗时,取决于最后一个BulkShardRequest请求的返回。这就很容易联想到分布式的长尾效应。

我们将ES索引的写入性能翻倍,我们下线了超过400台物理机(图4)

接下来再看一个现象,我们分析了某个节点的write线程的状态,发现节点有时候write线程全是runnable状态,有时候又有大量在waiting。此时写入是有瓶颈的,runnable状态可以理解,但却经常出现waiting状态。所以这也能印证了CPU利用率不高。同时也论证长尾效应的存在,因为长尾节点繁忙,ClientNode在等待繁忙节点返回BulkShardRequest请求,其他节点可能出现相对空闲的状态。下面是一个节点2个时刻的线程状态:

时刻一:

我们将ES索引的写入性能翻倍,我们下线了超过400台物理机(图5)

时刻二:

我们将ES索引的写入性能翻倍,我们下线了超过400台物理机(图6)

4、瓶颈分析

谷歌大神Jeffrey Dean《The Tail At Scale》介绍了长尾效应,以及导致长尾效应的原因。总结下来,就是正常请求都很快,但是偶尔单次请求会特别慢。这样在分布式操作时会导致长尾效应。我们从ES原理和实现中分析,造成ES单次请求特别慢的原因。发现了下面几个因素会造成长尾问题:

1lucene refresh

我们打开lucene引擎内部的一些日志,可以看到:

我们将ES索引的写入性能翻倍,我们下线了超过400台物理机(图7)

write线程是用来处理BulkShardRequest请求的,但是从截图的日志可以看到,write线程也会会进行refresh操作。这里面的实现比较复杂,简单说,就是ES定期会将写入buffer的数据refresh成segment,ES为了防止refresh不过来,会在BulkShardRequest请求的时候,判断当前shard是否有正在refresh的任务,有的话,就会帮忙一起分摊refresh压力,这个是在write线程中进行的。这样的问题就是造成单次BulkShardRequest请求写入很慢。还导致长时间占用了write线程。在write queue的原因会具体介绍这种危害。

我们将ES索引的写入性能翻倍,我们下线了超过400台物理机(图8)

2translog ReadWriteLock

ES的translog类似LSM-Tree的WAL log。ES实时写入的数据都在lucene内存buffer中,所以需要依赖写入translog保证数据的可靠性。ES translog具体实现中,在写translog的时候会上ReadLock。在translog过期、翻滚的时候会上WriteLock。这会出现,在WriteLock期间,实时写入会等待ReadLock,造成了BulkShardRequest请求写入变慢。我们配置的tranlog写入模式是async,正常开销是非常小的,但是从图中可以看到,写translog偶尔可能超过100ms。

我们将ES索引的写入性能翻倍,我们下线了超过400台物理机(图9)

3write queue

我们将ES索引的写入性能翻倍,我们下线了超过400台物理机(图10)

ES DataNode的写入是用标准的线程池模型是,一批active线程,我们一般配置为跟cpu个数相同。会有一个write queue,我们配置为1000。DataNode接收BulkShardRequest请求,先将请求放入write queue,active线程有空隙的,就会从queue中获取BulkShardRequest请求。这种模型下,当写入active线程繁忙的时候,queue中会堆积大量的请求。这些请求在等待执行,而从ClientNode角度看,就是BulkShardRequest请求的耗时变长了。下面日志记录了action的slowlog,其中waitTime就是请求等待执行的时间,可以看到等待时间超过了200ms。

4JVM GC

ES正常一次写入请求基本在亚毫秒级别,但是jvm的gc可能在几十到上百毫秒,这也增加了BulkShardRequest请求的耗时。这些加重长尾现象的case,会导致一个情况就是,有的节点很繁忙,发往这个节点的请求都delay了,而其他节点却空闲下来,这样整体cpu就无法充分利用起来。

5、论证结论

长尾问题主要来自于BulkRequest的一批请求会分散写入多个shard,其中有的shard的请求会因为上述的一些原因导致响应变慢,造成了长尾。如果每次BulkRequest只写入一个shard,那么就不存在写入等待的情况,这个shard返回后,ClientNode就能将结果返回给客户端,那么就不存在长尾问题了。

我们做了一个验证,修改客户端SDK,在每批BulkRequest写入的时候,都传入相同的routing值,写入相同的索引,这样就保证了BulkRequest的一批数据,都写入一个shard中。

我们将ES索引的写入性能翻倍,我们下线了超过400台物理机(图11)

优化后,第一个平稳曲线是,每个bulkRequest为10M的情况,写入速度在56w/s左右。之后将bulkRequest改为1M(10M差不多有4000条记录,之前写150个shard,所以bulkSize比较大)后,性能还有进一步提升,达到了65w/s。

从验证结果可以看到,每个bulkRequest只写一个shard的话,性能有很大的提升,同时cpu也能充分利用起来,这符合之前单节点压测的cpu利用率预期。

三、性能优化

从上面的写入瓶颈分析,我们发现了ES无法将资源用满的原因来自于分布式的长尾问题。于是我们着重思考如何消除分布式的长尾问题。也在探寻其他的优化点。整体性能优化,我们分成了三个方向:

横向优化,优化写入模型,消除分布式长尾效应。

纵向优化,提升单节点写入能力。

应用优化,探究业务节省资源的可能。

这次的性能优化,我们在这三个方向上都取得了一些突破。

1、 优化写入模型

写入模型的优化思路是将一个BulkRequest请求,到尽量少的shard,甚至只到一个shard,来减少甚至消除分布式长尾效应。我们完成的写入模型优化,最终能做到一个BulkRequest请求只到一个shard,这样就消除了分布式长尾效应。

写入模型的优化分成两个场景。一个是数据不带routing的场景,这种场景用户不依赖数据分布,比较容易优化的,可以做到只到一个shard。另一个是数据带了routing的场景,用户对数据分布有依赖,针对这种场景,我们也实现了一种优化方案。

1不带routing场景

由于用户对routing分布没有依赖,ClientNode在处理BulkRequest请求中,给BulkRequest的一批请求带上了相同的随机routing值,而我们生成环境的场景中,一批数据是写入一个索引中,所以这一批数据就会写入一个物理shard中。

我们将ES索引的写入性能翻倍,我们下线了超过400台物理机(图12)

2带routing场景

下面着重介绍下我们在带routing场景下的实现方案。这个方案,我们需要在ES Server层和ES SDK都进行优化,将两者综合使用,来达到一个BulkRequest上的一批数据写入一个物理shard的效果。优化思路ES SDK做一次数据分发,在ES Server层做一次随机写入来让一批数据写入同一个shard。

先介绍下Server层引入的概念,我们在ES shard之上,引入了逻辑shard的概念,命名为`number_of_routing_size` 。ES索引的真实shard我们称之为物理shard,命名是`number_of_shards`。

物理shard必须是逻辑shard的整数倍,这样一个逻辑shard可以映射到多个物理shard。一组逻辑shard,我们命名为slot,slot总数为`number_of_shards / number_of_routing_size`。

数据在写入ClientNode的时候,ClientNode会给BulkRequest的一批请求生成一个相同的随机值,目的是为了让写入的一批数据,都能写入相同的slot中。数据流转如图所示:

我们将ES索引的写入性能翻倍,我们下线了超过400台物理机(图13)

最终计算一条数据所在shard的公式如下:

slot = hashrandomvalue % number_of_shards/number_of_routing_size

shard_num = hash(_routing) % number_of_routing_size + number_of_routing_size * slot

我们在ES SDK层进一步优化,在BulkProcessor写入的时候增加逻辑shard参数,在add数据的时候,可以按逻辑shard进行hash,生成多个BulkRequest。这样发送到Server的一个BulkRequest请求,只有一个逻辑shard的数据。最终,写入模型变为如下图所示:

我们将ES索引的写入性能翻倍,我们下线了超过400台物理机(图14)

经过SDK和Server的两层作用,一个BulkRequest中的一批请求,写入了相同的物理shard。

这个方案对写入是非常友好的,但是对查询会有些影响。由于routing值是对应的是逻辑shard,一个逻辑shard要对应多个物理shard,所以用户带routing的查询时,会去一个逻辑shard对应的多个物理shard中查询。

我们针对优化的是日志写入的场景,日志写入场景的特征是写多读少,而且读写比例差别很大,所以在实际生产环境中,查询的影响不是很大。

2、单节点写入能力提升

单节点写入性能提升主要有以下优化:

backport社区优化,包括下面2方面:

merge 社区flush优化特性:27000 Dont refresh on `_flush` `_force_merge` and `_upgrade`。

merge 社区translog优化特性,包括下面2个:

45765 Do sync before closeIntoReader when rolling generation to improve index performance

47790 sync before trimUnreferencedReaders to improve index preformance

这些特性我们在生产环境验证下来,性能大概可以带来18%的性能提升。

我们还做了2个可选性能优化点:

优化translog,支持动态开启索引不写translog,不写translog的话,我们可以不再触发translog的锁问题,也可以缓解了IO压力。但是这可能带来数据丢失,所以目前我们做成动态开关,可以在需要追数据的时候临时开启。后续我们也在考虑跟flink团队结合,通过flink checkpoint保证数据可靠性,就可以不依赖写入translog。从生产环境我们验证的情况看,在写入压力较大的索引上开启不写translog,能有10-30%不等的性能提升。

优化lucene写入流程,支持在索引上配置在write线程不同步flush segment,解决前面提到长尾原因中的lucene refresh问题。在生产环境上,我们验证下来,能有7-10%左右的性能提升。

不清洗大的冗余字段,我们验证下来,能有20%左右的性能提升,该优化同时还带来了10%左右存储空间节约。

四、生产环境性能提升结果

1、 写入模型优化

我们重点看下写入模型优化的效果,下面的优化,都是在客户端、服务端资源没做任何调整的情况下的生产数据。

下图所示索引开启写入模型优化后,写入tps直接从50w/s,提升到120w/s。

我们将ES索引的写入性能翻倍,我们下线了超过400台物理机(图15)

生产环境索引写入性能的提升比例跟索引混部情况、索引所在资源大小(长尾问题影响程度)等因素影响。从实际优化效果看,很多索引都能将写入速度翻倍,如下图所示:

我们将ES索引的写入性能翻倍,我们下线了超过400台物理机(图16)

2、 写入拒绝量(write rejected)下降

再来看一个关键指标,写入拒绝量(write rejected)ES datanode queue满了之后就会出现rejected。

rejected异常带来个危害,一个是个别节点出现rejected,说明写入队列满了,大量请求在队列中等待,而region内的其他节点却可能很空闲,这就造成了cpu整体利用率上不去。

rejected异常另一个危害是造成失败重试,这加重了写入负担,增加了写入延迟的可能。

优化后,由于一个bulk请求不再分到每个shard上,而是写入一个shard。一来减少了写入请求,二来不再需要等待全部shard返回。

我们将ES索引的写入性能翻倍,我们下线了超过400台物理机(图17)

3、延迟情况缓解

最后再来看下写入延迟问题。经过优化后,写入能力得到大幅提升后,极大的缓解了当前的延迟情况。下面截取了集群优化前后的延迟情况对比。

我们将ES索引的写入性能翻倍,我们下线了超过400台物理机(图18)

五、总结

本文相关词条概念解析:

索引

索引,使用索引可快速访问数据库表中的特定信息。索引是对数据库表中一列或多列的值进行排序的一种结构。在关系数据库中,索引是一种与表有关的数据库结构,它可以使对应于表的SQL语句执行得更快。索引的作用相当于图书的目录,可以根据目录中的页码快速找到所需的内容。当表中有大量记录时,若要对表进行查询,第一种搜索信息方式是全表搜索,是将所有记录一一取出,和查询条件进行一一对比,然后返回满足条件的记录,这样做会消耗大量数据库系统时间,并造成大量磁盘I/O操作;第二种就是在表中建立索引,然后在索引中找到符合查询条件的索引值,最后通过保存在索引中的ROWID(相当于页码)快速找到表中对应的记录。索引是一个单独的、物理的数据库结构,它是某个表中一列或若干列值的集合和相应的指向表中物理标识这些值的数据页的逻辑指针清单。索引提供指向存储在表的指定列中的数据值的指针,然后根据您指定的排序顺序对这些指针排序。数据库使用索引的方式与您使用书籍中的索引的方式很相似:它搜索索引以找到特定值,然后顺指针找到包含该值的行。在数据库关系图中,可以在选定表的“索引/键”属性页中创建、编辑或删除每个索引类型。当保存索引所附加到的表,或保存该表所在的关系图时,索引将保存在数据库中。

相关资讯

  • 猿辅导凭什么超级吸金

    猿辅导凭什么超级吸金

    允中 发自 凹非寺技术之力,不仅在重塑教育领域,更在重构教育行业格局。猿辅导就是最新、最好的证明。或者现在该说:全球教育科技第一独角兽公司 猿辅导了。在今天(10月22日)猿辅导官宣了新一轮融资,获投

    10-23
  • 携手中国联通展示MAD,Gaze产品,开启VR新视界

    携手中国联通展示MAD,Gaze产品,开启VR新视界

    10月18日-20日,由工业和信息化部及江西省人民政府主办、全球AR/VR领域备受行业瞩目,规模最大、规格最高的“2020世界VR产业大会”在江西南昌举行。作为中国乃至全球AR/VR科技创新发展的风向

    10-23
  • 在iPhone12正式发售后,同时也是北京苏宁易购的老顾客

    在iPhone12正式发售后,同时也是北京苏宁易购的老顾客

    10月14日iPhone12正式预售,预售新闻发布后热搜持续不断,早就按耐不住的“果粉”纷纷开启“预约模式”希望能够在第一时间拿到期待已久的新机。10月23日早,在iPhone12正式发售后,北京苏宁

    10-23
  • 成龙代言霸王洗发水,不过周杰伦救不了美邦,如今还可以救海澜之家么

    成龙代言霸王洗发水,不过周杰伦救不了美邦,如今还可以救海澜之家么

    在中国商界,成龙代言绝对是一个魔咒。在成龙过去的代言历史上,可能只有格力一家公司抗住了,没有倒下还越做越大了。成龙代言垮掉的产品真的是不计其数。成龙代言霸王洗发水,结果霸王出现了毒药事情,同时创始人夫

    10-23
  • iPhone,为什么这几年一直没有像安卓这样升级

    iPhone,为什么这几年一直没有像安卓这样升级

    iPhone12系列刚刚发布,手机还没有到用户手中,关于下一代iPhone13的初见端倪,不过大部分都是捕风捉影,很难有事实依据作为支撑。也有一些可靠性比较高,比如苹果依旧没有放弃Touch ID相关

    10-23
  • 此次下线的是一台智慧冰箱,海尔冰箱的挑战在哪里

    此次下线的是一台智慧冰箱,海尔冰箱的挑战在哪里

    在答案揭晓之前,我们不妨通过各大调研机构的数据来做个梳理,看看海尔冰箱如今的市场地位。俗话说“打铁还需自身硬”根据欧睿国际发布的2019年全球家电市场调查数据显示,海尔制冷以17.8%的全球品牌零售量

    04-01

相关推荐

  • 同和药业追求全员参与,同和药业可转债发行网上路

    同和药业追求全员参与,同和药业可转债发行网上路

    同和药业可转债发行网上路演10月23日 -本活动于2020年10月23日(星期五)-举行,欢迎广大投资者踊跃参与!参与嘉宾公司简介公司主要从事原料药的生产,产品出口全球50多个国家和地区,外销占比85

    10-23
  • 小米快速液晶显示器24.5英寸正式发布,但首批预售到手价仅999元

    小米快速液晶显示器24.5英寸正式发布,但首批预售到手价仅999元

    今天,小米快速液晶显示器24.5英寸正式发布,该显示器的定位是电竞市场。作为一款电竞显示器,小米快速液晶显示器24.5英寸采用1080P分辨率,支持144Hz高刷新率,可以带来更精准、流畅的游戏画面体

    10-23
  • TCL华星光电着力提高效率,金旴植,广州面板项目明年动工

    TCL华星光电着力提高效率,金旴植,广州面板项目明年动工

    10月22日,TCL科技旗下TCL华星光电在其全球显示生态大会(DTC 2020)上发布了云卷屏、卷轴屏等4款新品,并宣布未来五年将以TV(电视)面板为主,向全技术、全产品、全场景进行战略转型。“公司

    10-23
  • 已向特斯拉公司发出邀请,马斯克,明年一定去

    已向特斯拉公司发出邀请,马斯克,明年一定去

    印度最为富裕的马哈拉施特拉邦 (Maharashtra)已向特斯拉公司发出邀请,要求美国这家电动汽车制造商去该邦投资建厂。当地时间周四,马哈拉施特拉邦旅游和环境部长阿迪蒂亚 · 萨克雷(Aaditya

    10-23
  • 深化保险供给侧结构性改革

    深化保险供给侧结构性改革

    在10月15日举办的中国寿险业转型发展峰会上,中国银副主席黄洪讲话时提出,人身保险业应全力实现高质量发展、实现转型突围。人身险业应继续深化改革,深化保险供给侧结构性改革,优化产品和服务,更好地满足消费

    10-23
  •  张璐说道,在后疫情时代

    张璐说道,在后疫情时代

    时间走到Q2,全球大部分地区都受新冠肺炎的影响,导致科技初创企业大量裁员,似乎一夜之间都转向远程工作。除此之外,旅游业、最后一英里的出行、餐馆、广告等行业都遭受了重创。而随着疫情在北美及全球持续肆虐,

    10-23

网友评论