Elasticsearch写入优化

本文涉及的产品
实时数仓Hologres,5000CU*H 100GB 3个月
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
实时计算 Flink 版,5000CU*H 3个月
简介: 【10月更文挑战第3天】Elasticsearch:从写入原理谈写入优化

写入优化一:副本分片写入前置为0,等完成写入后复原副本
PUT test-0001
{
"settings": {
"number_of_replicas": 0
}
}
写入优化二:优先使用系统自动生成 id
文档的_id 的生成有两种方式,

第一:系统自动生成id。

第二:外部控制自增id。

但,如果使用外部 id,Elasticsearch 会先尝试读取原来文档的版本号,以判断是否需要更新。

也就是说,使用外部控制 id 比系统自动生成id要多一次读取磁盘操作。

所以,非特殊场景推荐使用系统自动生成的 id。

4、基于 Elasticsearch 写入原理谈写入优化
Elasticsearch 中的 1 个索引由一个或多个分片组成,每个分片包含多个segment(段),每一个段都是一个倒排索引

在 lucene 中,为了实现高索引速度,使用了segment 分段架构存储。一批写入数据保存在一个段中,其中每个段最终落地为磁盘中的单个文件。

将文档插入 Elasticsearch 时,它们会被写入缓冲区中,然后在刷新时定期从该缓冲区刷新到段中。刷新频率由 refresh_interval 参数控制,默认每1秒刷新一次。

也就是说,新插入的文档在刷新到段(内存中)之前,是不能被搜索到的

刷新的本质是:写入数据由内存 buffer 写入到内存段中,以保证搜索可见。

来看个例子,加深对 refresh_inteval 的理解,注释部分就是解读。

PUT test_0001/_doc/1
{
"title":"just testing"
}

默认一秒的刷新频率,秒级可见(用户无感知)

GET test_0001/_search
如下设置后,写入后 60s 后才可见。

DELETE test_0001

设置了60s的刷新频率

PUT test_0001
{
"settings": {
"index":{
"refresh_interval":"60s"
}
}
}

PUT test_0001/_doc/1
{
"title":"just testing"
}

60s后才可以被搜索到

GET test_0001/_search
关于是否需要实时刷新:

如果新插入的数据需要近乎实时的搜索功能,则需要频繁刷新。

如果对最新数据的检索响应没有实时性要求,则应增加刷新间隔,以提高数据写入的效率。

所以,自然我们想到的优化是:调整刷新频率。

写入优化三:合理调整刷新频率
调整方法如下:

方法1:写入前刷新频率设置为 -1,写入后设置为业务实际需要值(比如:30s)。

PUT test-008
{
"settings": {
"refresh_interval": -1
}
}
方法2:直接设置为业务实际需要值(比如:30s)

PUT test-008
{
"settings": {
"refresh_interval": "30s"
}
}
写入优化四:合理调整堆内存中索引缓冲区(index_buffer)大小
堆内存中 index_buffer 用于存储新索引的文档。

填满后,缓冲区中的文档将最终写入磁盘上的某个段。

index_buffer_size 默认值如下所示,为堆内存的 10%。

indices.memory.index_buffer_size: 10%
例如,如果给 JVM 31GB的内存,它将为索引缓冲区提供 3.1 GB的内存,一般情况下足以容纳大量数据的写入操作。

但,如果着实数据量非常大,建议调大该默认值。比如:调整为堆内存的 20%。

调整建议:必须在集群中的每个数据节点上进行配置。

缓存区越大,意味着能缓存数据量越大,相同时间段内,写盘频次低、磁盘 IO 小,间接提升写入性能。

写入优化五:给堆外内存也留够空间(常规要求)
这其实算不上写入优化建议,而是通用集群配置的常规配置。

内存分配设置堆内存比例官方建议:机器内存大小一半,但不超过 32 GB。

一般设置建议:

如果内存大小 >= 64 GB,堆内存设置:31 GB。

如果内存大小 < 64 GB,堆内存设置:内存大小一半。

堆内存之外的内存留给:Lucene 使用。

推荐阅读:干货 | 吃透Elasticsearch 堆内存

写入优化六:bulk 批量写入而非单个文档写入
批量写入自然会比单个写入性能要好(批量写入意味着相同时间产生的段会大,段的总个数自然会少),但批量值的设置一般需要慎重,不要盲目一下搞的很大。

一般建议:递增步长测试,直到达到资源使用上限。

比如:第一次批量值设置:100,第二次:200,第三次:400,以此类推......

批量值 bulk 已经 ok 了,但集群尚有富余资源,资源利用并没有饱和怎么办?

上多线程,通过并发提升写入性能。

写入优化七:多线程并发写入
这点,在 logstash 同步数据到 Elasticsearch,基于spark、kafka、Flink 批量写入 Elasticsearch时,经常会出现:Bulk Rejections 的报错。

当批量请求到达集群中的某个节点时,整个请求将被放入批量队列中,并由批量线程池中的线程进行处理。批量线程池处理来自队列的请求,并将文档转发到副本分片,作为此处理的一部分。子请求完成后,将响应发送到协调节点。

Elasticsearch 具有有限大小的请求队列的原因是:为了防止集群过载,从而增加了稳定性和可靠性。

如果没有任何限制,客户端可以很容易地通过恶意攻击行为将整个集群搞宕机。

这里就引申出下面的优化点。

写入优化八:合理设置线程池和队列大小
关于线程池和队列,参考:Elasticsearch 线程池和队列问题,请先看这一篇。

核心建议就是:结合 CPU 核数和 esrally 的测试结果谨慎的调整 write 线程池和队列大小。

为什么要谨慎设置?

针对批量写入拒绝(reject)的场景,官方建议:

增加队列的大小不太可能改善集群的索引性能或吞吐量。相反,这只会使集群在内存中排队更多数据,这很可能导致批量请求需要更长的时间才能完成。

队列中的批量请求越多,将消耗更多的宝贵堆空间。如果堆上的压力太大,则可能导致许多其他性能问题,甚至导致集群不稳定。

推荐阅读:

https://www.elastic.co/cn/blog/why-am-i-seeing-bulk-rejections-in-my-elasticsearch-cluster

5、其他写入优化建议
写入优化九:设置合理的Mapping
实战业务场景中不推荐使用默认 dynamic Mapping,一定要手动设置 Mapping。

举例1:默认字符串类型是:text 和 keyword 的组合类型,就不见得适用所有业务场景。要结合自己业务场景设置,正文 cont 文本内容一般不需要设置 keyword 类型(因为:不需要排序和聚合操作)。

举例2:互联网采集数据存储场景,正文需要全文检索,但包含 html 样式的文本一般留给前端展示用,不需要索引。这时候Mapping 设置阶段要果断将 index 设置为 false。

写入优化十:合理的使用分词器
分词器决定分词的粒度,常见的中文分词 IK 可细分为:

粗粒度分词:ik_smart。

细粒度分词:ik_max_word。

从存储角度基于 ik_max_word 分词的索引会比基于 ik_smart 分词的索引占据空间大。

而更细粒度自定义分词 ngram 会占用大量资源,并且可能减慢索引速度并显着增加索引大小。

所以要结合检索指标(召回率和精准率)、结合写入场景斟酌选型。

写入优化十一:必要时,使用 SSD 磁盘
SSD 很贵,但很香。

尤其针对写入密集型场景,如果其他优化点都考虑了,这可能是你最后一根“救命稻草“。

写入优化十二:合理设置集群节点角色
这也是经常被问到的问题,集群规模小的时候,一般节点会混合多种角色,如:主节点 + 数据节点、数据节点 + 协调节点混合部署。

但,集群规模大了之后,硬件资源相对丰富后,强烈建立:独立主节点、独立协调节点。

让各个角色的节点各尽其责,对写入、检索性能都会有帮助。

写入优化十三:推荐使用官方客户端
推荐使用官方 Elasticsearch API,因为官方在连接池和保持连接状态方面有优化。

高版本 JAVA API 推荐:官方的High-level-Rest API。

其他写入优化
待补充......

6、写入过程中做好监控
如下是 kibana 监控截图,其中:index Rate 就是写入速率。

index rate: 每秒写入的文档数。

search rate:每秒的查询次数(分片级别,非请求级别),也就意味着一次查询请求命中的分片数越多,值越大。

目录
相关文章
|
25天前
|
弹性计算 人工智能 架构师
阿里云携手Altair共拓云上工业仿真新机遇
2024年9月12日,「2024 Altair 技术大会杭州站」成功召开,阿里云弹性计算产品运营与生态负责人何川,与Altair中国技术总监赵阳在会上联合发布了最新的“云上CAE一体机”。
阿里云携手Altair共拓云上工业仿真新机遇
|
2天前
|
人工智能 Rust Java
10月更文挑战赛火热启动,坚持热爱坚持创作!
开发者社区10月更文挑战,寻找热爱技术内容创作的你,欢迎来创作!
279 12
|
17天前
|
存储 关系型数据库 分布式数据库
GraphRAG:基于PolarDB+通义千问+LangChain的知识图谱+大模型最佳实践
本文介绍了如何使用PolarDB、通义千问和LangChain搭建GraphRAG系统,结合知识图谱和向量检索提升问答质量。通过实例展示了单独使用向量检索和图检索的局限性,并通过图+向量联合搜索增强了问答准确性。PolarDB支持AGE图引擎和pgvector插件,实现图数据和向量数据的统一存储与检索,提升了RAG系统的性能和效果。
|
5天前
|
JSON 自然语言处理 数据管理
阿里云百炼产品月刊【2024年9月】
阿里云百炼产品月刊【2024年9月】,涵盖本月产品和功能发布、活动,应用实践等内容,帮助您快速了解阿里云百炼产品的最新动态。
阿里云百炼产品月刊【2024年9月】
|
20天前
|
人工智能 IDE 程序员
期盼已久!通义灵码 AI 程序员开启邀测,全流程开发仅用几分钟
在云栖大会上,阿里云云原生应用平台负责人丁宇宣布,「通义灵码」完成全面升级,并正式发布 AI 程序员。
|
22天前
|
机器学习/深度学习 算法 大数据
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
2024“华为杯”数学建模竞赛,对ABCDEF每个题进行详细的分析,涵盖风电场功率优化、WLAN网络吞吐量、磁性元件损耗建模、地理环境问题、高速公路应急车道启用和X射线脉冲星建模等多领域问题,解析了问题类型、专业和技能的需要。
2583 22
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
|
4天前
|
存储 人工智能 搜索推荐
数据治理,是时候打破刻板印象了
瓴羊智能数据建设与治理产品Datapin全面升级,可演进扩展的数据架构体系为企业数据治理预留发展空间,推出敏捷版用以解决企业数据量不大但需构建数据的场景问题,基于大模型打造的DataAgent更是为企业用好数据资产提供了便利。
175 2
|
2天前
|
编译器 C#
C#多态概述:通过继承实现的不同对象调用相同的方法,表现出不同的行为
C#多态概述:通过继承实现的不同对象调用相同的方法,表现出不同的行为
101 65
|
5天前
|
Linux 虚拟化 开发者
一键将CentOs的yum源更换为国内阿里yum源
一键将CentOs的yum源更换为国内阿里yum源
273 2
|
21天前
|
机器学习/深度学习 算法 数据可视化
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码
2024年中国研究生数学建模竞赛C题聚焦磁性元件磁芯损耗建模。题目背景介绍了电能变换技术的发展与应用,强调磁性元件在功率变换器中的重要性。磁芯损耗受多种因素影响,现有模型难以精确预测。题目要求通过数据分析建立高精度磁芯损耗模型。具体任务包括励磁波形分类、修正斯坦麦茨方程、分析影响因素、构建预测模型及优化设计条件。涉及数据预处理、特征提取、机器学习及优化算法等技术。适合电气、材料、计算机等多个专业学生参与。
1580 16
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码