前言
项目性能测试的时候存在每条任务都有百万数据量入库的情况,ES入库速度较慢,导致Kafka消息堆积,需要提升入库速率,下为参考收集整理的内容。
一、硬件优化
- 使用SSD代替机械硬盘
- 使用多块硬盘 (Elasticsearch 通过多个 path.data 目录配置)
当前服务器使用的均是1T的SSD且暂不支持使用多块硬盘
二、分片策略
1、分片数与副本数
分片数
- 建议:集群节点的个数 <= 分片个数 <= 节点数的3倍
- 每个分片占用的硬盘容量不超过 ES 的最大 JVM 的堆空间设置(一般设置不超过 32G)
- 参考关:系节点数<=主分片数*(副本数+1)
除非重新创建索引,不然分片数无法修改
副本数
- 除非你对系统的健壮性有异常高的要求,比如:银行系统。可以考虑2个副本以上。否则,1个副本足够。
2、节点类型分配
- 集群节点数:<= 3,建议:所有节点的master:true, data:true。既是主节点也是路由节点。
- 集群节点数:> 3, 根据业务场景需要,建议:逐步独立出Master节点和协调/路由节点。
三、优化写入速度
1、增加refresh间隔
- 设置index.refresh_interval参数,延长refresh间隔可以有效地减少段刷新次数,但这同时意味着需要消耗更多的 Heap 内存
- 设置refresh_interval 为-1,同时设置number_of_replicas 为0,通过关闭refresh间隔周期,同时不设置副本来提高写性能
Lucene 在新增数据时,采用了延迟写入的策略,默认情况下索引的 refresh_interval 为1 秒。如果我们将这个间隔调大,比如30s,可以接受写入的数据30s后才看到,那么我们就可以获取更大的写入吞吐量,因为30s内都是写内存的,每隔30s才会创建一个segment file。
2、减少副本数
- 如 果 我 们 需 要 大 批量 进 行 写 入 操 作 , 可 以 先 禁 止 Replica 复 制 , 设 置 index.number_of_replicas: 0 关闭副本。在写入完成后,Replica 修改回正常的状态。
ES 为了保证集群的可用性,提供了 Replicas(副本)支持,然而每个副本也会执行分析、索引及可能的合并过程,所以 Replicas 的数量会严重影响写索引的效率。当写索引时,需要把写入的数据都同步到副本节点,副本节点越多,写索引的效率就越慢。
3、批量写入
- 批量写入的大小要结合队列的大小,而队列大小和线程池大小、机器的cpu核数。
先bulk写入100个document,然后200个,400个,以此类推,每次都将bulk size加倍一次。如果bulk写入性能开始变平缓的时候,那么这个就是最佳的bulk大小,过大的bulk size会导致内存压力过大
4、使用多线程将数据写入es
首先对单个es节点的单个shard做压测,比如说,先是2个线程,然后是4个线程,然后是8个线程,16个,每次线程数量倍增。一旦发现es返回了TOO_MANY_REQUESTS的错误,JavaClient也就是EsRejectedExecutionException。此时那么就说明es是说已经到了一个并发写入的最大瓶颈了,此时我们就知道最多只能支撑这么高的并发写入了。
5、使用默认Id
如果我们要手动给es document设置一个id,那么es需要每次都去确认一下那个id是否存在,这个过程是比较耗费时间的。如果我们使用自动生成的id,那么es就可以跳过这个步骤,写入性能会更好。对于你的业务中的表id,可以作为es document的一个field。
6、内存设置
在 ES 安装文件中包含一个 jvm.option 文件,添加如下命令来设置 ES 的堆大小,Xms 表示堆的初始大小,Xmx 表示可分配的最大内存。
- 确保 Xmx 和 Xms 的大小是相同的,其目的是为了能够在 Java 垃圾回收机制清理完堆区后不需要重新分隔计算堆区的大小而浪费资源,可以减轻伸缩堆大小带来的压力。
- 不要超过物理内存的 50%
|