ES写入性能优化

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


解决方案

1. 读数据

首先要从数仓读取出数据到内存。而后再组装对象去ES刷数据字段比较多并且都须要查询。尝试了一下,即便limit 10,也须要耗时2分钟。因此第一步导数据不能直接查询。采用的是数仓到分布式文件系统分片存储。这一步已经有现成工具。1亿数据导入到分片耗时3分钟左右sql

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的索引速率 google

成果

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

相关文章
相关标签/搜索