资讯专栏INFORMATION COLUMN

ES写入性能优化

dailybird / 752人阅读

摘要:大多数字段都是统计数据,无法区分哪些发生了变化,所以不能增量更新。于是做了一些写入优化。之前写业务代码数据量一般不是很大,采用的是一次性把数据读取到内存中。用查看刷数据机器的性能可以看到开启的个线程占用内存。

背景: 有1亿多的用户画像中数仓需要导入ES。大多数字段都是sql统计数据,无法区分哪些发生了变化,所以不能增量更新。只能每天全量刷数据。在刷数据的过程中出现了更新缓慢、内存问题。于是做了一些写入优化。

*

解决方案 1. 读数据
首先要从数仓读取出数据到内存。然后再组装对象去ES刷数据字段比较多而且都需要查询。尝试了一下,即使limit 10,也需要耗时2分钟。所以第一步导数据不能直接查询。采用的是数仓到分布式文件系统分片存储。这一步已经有现成工具。1亿数据导入到分片耗时3分钟左右
2.组装数据
将分片的数据读到java内存中。再构造请求参数刷ES

`问题:1.刷数据ES报413错误。ES建议每次bulk5~15M数据,这里我每次批量提交5000条,bulk的时候发生的413 requets too large错误,google了一下,说是索引的时候段合并内存不够。于是调整indices.breaker.fielddata.limit为60%,增大堆内存,结果没什么用;也有说要调整 client_max_body_size 的,但是我们的es是云服务,没法改配置参数最终加大es的内存为16G,不再报这个错误。

2.之前写业务代码数据量一般不是很大,采用的是一次性把数据读取到内存中。再做业务处理。但是这次在数据塞到一半的数据,先是系统响应变慢了,后来测试环境的系统挂了。通过过命令排查,发现List对象占用了很多空间。于是复查代码。发现是for循环一直往list填对象导致的内存泄露。于是限制了单个文件大小为20M,一个文件一个文件地处理。
`

3.提高es索引效率
刚开始刷数据预计需要20个小时。今天的数据如果明天才更新完,意义不大。于是想办法提高索引效率。网上都说"refresh_interval": "-1";调整number_of_replicas=0。我调整了结果没什么变化。于是采用多线程刷数据

问题:1.一开始使用size为20的无界队列,导致耗尽资源,任务线程占用的内存占用了80+%的内存,其他任务可能被拖垮。后来线程的核心线程数和最大线程数统一设置为10。并采用future模式,一个任务完成后再去添加其他任务。解决了线程耗尽资源和内存的问题。

用htop查看刷数据机器的性能

可以看到开启的10个线程占用42%内存。主线程cpu偶尔接近100%,这不是io密集型吗?怎么会耗cpu。cpu变高可能是复杂的技术或者死循环。这里循环每次读取量有50000条,并且组装对象的逻辑。而且有10个线程,猜想可能是这个原因。

ES的索引速率

成果
最后原来需要20小时才能完成的刷数据任务,只耗时约100分钟。当然中间遇到的坑不止这些

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/73457.html

相关文章

  • ES分布式架构及底层原理

    摘要:分布式架构原理设计的理念就是分布式搜索引擎,底层实现还是基于的,核心思想是在多态机器上启动多个进程实例,组成一个集群。 es分布式架构原理 elasticsearch设计的理念就是分布式搜索引擎,底层实现还是基于Lucene的,核心思想是在多态机器上启动多个es进程实例,组成一个es集群。一下是es的几个概念: 接近实时es是一个接近实时的搜索平台,这就意味着,从索引一个文档直到文档...

    Ocean 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<