【实战 ES】实战 Elasticsearch:快速上手与深度实践-2.3.1 避免频繁更新(Update by Query的代价)

👉 点击关注不迷路
👉 点击关注不迷路
👉 点击关注不迷路


文章大纲

  • Elasticsearch数据更新与删除深度解析:2.3.1 避免频繁更新(Update by Query的代价)
    • 案例背景
    • 1. `Update by Query`的内部机制解析
      • 1.1 文档更新底层实现原理
      • 1.2 更新操作资源消耗模型
    • 2. 频繁更新引发的性能问题
      • 2.1 分段(`Segment`)爆炸效应
      • 2.2 版本控制开销
      • 2.3 真实问题诊断数据
    • 3. 真实场景压力测试数据
      • 3.1 测试环境
      • 3.2 不同更新频率对比(更新频率与性能衰减关系)
      • 3.3 性能衰减曲线
    • 4. 优化方案与替代策略
      • 4.1 数据结构优化
      • 4.2 写入模式改造
      • 4.3 版本控制优化配置
    • 5. 生产环境故障恢复实践
      • 5.1 紧急止血方案
      • 5.2 长期治理措施
      • 5.3 效果验证
    • 关键结论与最佳实践
      • 避坑指南
      • 终极解决方案

Elasticsearch数据更新与删除深度解析:2.3.1 避免频繁更新(Update by Query的代价)

案例背景

某物流追踪平台在业务升级后出现集群性能断崖式下降

  • 数据规模:每日处理5亿条物流状态更新
  • 更新模式:使用_update_by_query实时修改运单状态
  • 问题表现
    • 写入吞吐量从12万ops/s暴跌至2.3万ops/s
    • 查询延迟P99从180ms上升到2100ms
    • 磁盘IOPS持续保持98%以上

1. Update by Query的内部机制解析

1.1 文档更新底层实现原理

Update请求
创建新文档
标记旧文档为删除
Refresh操作后可见
Segment Merge时物理删除
  • 关键特性对比(不同写操作资源消耗对比):
操作类型写入放大系数磁盘IO类型是否触发Merge
Index(新建)1x顺序写入低概率
Update(更新)3-5x随机读写混合必然触发
Delete(删除)2-3x随机读+顺序写中等概率

1.2 更新操作资源消耗模型

  • 单次更新成本公式:
总消耗 = 读操作(获取原文) + 写操作(新文档) + 删除标记 + 版本更新
        2.5 × 文档大小 × 副本数
  • 典型资源消耗比例:
    • CPU消耗:比新建操作高40-60%
    • 磁盘IO:比新建操作高300-500%
    • 内存压力:需要维护版本映射表

2. 频繁更新引发的性能问题

2.1 分段(Segment)爆炸效应

  • 更新操作对Lucene段的影响:
# 查看分段状态
GET /_cat/segments?v

# 问题集群输出示例:
index      shard prirep segment generation docs.count size.mb
logs-2023  0     p      _6               1500000    350
logs-2023  0     p      _7               800000     180  # 更新产生的分段
logs-2023  0     p      _8               750000     170
  • 分段异常特征:
    • 小分段(<100MB)数量超过50个
    • 单个分片分段总数超过100
    • 存在大量docs.deleted>30%的分段

2.2 版本控制开销

  • 版本号映射表内存消耗:
总内存消耗  文档数 × 16 bytes × 副本数
  • 对于1亿文档的索引:
16B × 100,000,000 × 2 = 3.2GB

2.3 真实问题诊断数据

// 节点性能分析
{
    // "io" 部分包含了与磁盘输入输出(I/O)操作相关的性能指标
    "io": {
        // "write_throughput" 表示磁盘的写入吞吐量,即单位时间内磁盘能够写入的数据量
        // 这里显示为 "450MB/s",但注释提示正常值应小于 200MB/s
        // 较高的写入吞吐量可能意味着系统正在进行大量的数据写入操作,可能会对磁盘性能造成较大压力
        "write_throughput": "450MB/s",  // 正常值<200MB/s
        
        // "iowait_percent" 表示 CPU 等待磁盘 I/O 操作完成的时间占比
        // 这里的值为 98.7,意味着 CPU 大部分时间都在等待磁盘 I/O 操作,磁盘 I/O 可能成为系统的性能瓶颈
        //  iowait 可能会导致系统响应变慢,影响应用程序的性能
        "iowait_percent": 98.7
    },
    
    // "jvm" 部分包含了与 Java 虚拟机(JVM)相关的性能指标
    "jvm": {
        // "old_gc_count" 表示老年代垃圾回收(Old GC)的次数
        // 注释提示正常情况下老年代垃圾回收次数应小于 5 /分钟
        // 这里显示为 35,说明老年代垃圾回收过于频繁
        // 频繁的老年代垃圾回收会导致系统停顿,影响应用程序的响应时间和吞吐量
        "old_gc_count": 35,            // 正常<5/分钟
        
        // "buffer_pools" 表示 JVM 中的缓冲区池信息
        "buffer_pools": {
            // "direct" 表示直接缓冲区池的使用情况
            // "4.2GB/5GB" 表示当前直接缓冲区池已使用 4.2GB 的内存,总容量为 5GB
            // 这反映了堆外内存的使用情况,较高的使用比例可能会导致堆外内存压力增大,甚至可能引发内存溢出错误
            
            "direct": "4.2GB/5GB"        // 堆外内存压力
        }
    }
}

3. 真实场景压力测试数据

3.1 测试环境

组件配置详情
ES集群3节点(16C64G NVMe SSD)
测试数据集1亿条物流数据(含15个字段)
测试模式持续30分钟混合负载(更新+查询)

3.2 不同更新频率对比(更新频率与性能衰减关系)

更新频率吞吐量(ops/s)磁盘IOPS段数量/分片GC停顿(s/min)
100次/秒82,00018,000120.8
500次/秒47,00053,000383.2
1000次/秒19,00089,000716.5
2000次/秒服务不可用100%120+Full GC卡死

3.3 性能衰减曲线

Throughput (k ops/s)
100 ┤■■■■■■■■■■■■■■■■■■■■
 80 ┤■■■■■■■■■■■□□□□□□□□
 60 ┤■■■■■■■□□□□□□□□□□□□
 40 ┤■■■□□□□□□□□□□□□□□□□
 20 ┤□□□□□□□□□□□□□□□□□□□
    └───────────────────
      原始负载  更新+10%  更新+30%  更新+50%
  • 吞吐量的单位是千操作每秒(k ops/s)
    • 原始负载:对应柱状图高度达到 100 k ops/s 的柱子。这表明在原始负载的情况下,系统的吞吐量能够达到 100 千操作每秒,此时系统处于一个相对稳定且高效的处理状态。
    • 更新 +10%:柱状图高度约为 80 k ops/s。当负载在原始基础上增加 10% 时,系统的吞吐量下降到了 80 千操作每秒。这可能是因为系统开始受到额外负载的影响,资源逐渐变得紧张,但仍能保持较高的处理能力。
    • 更新 +50%:柱状图高度约为 40 k ops/s。当负载增加到原始负载的 50% 时,系统的吞吐量大幅下降到 40 千操作每秒。这显示出系统在高负载下已经难以维持高效的处理能力,可能出现了性能瓶颈,如 CPU 使用率过高、内存不足、磁盘 I/O 瓶颈等问题。

4. 优化方案与替代策略

4.1 数据结构优化

  • 不可变数据模型设计
    • 在不可变数据模型里,一旦数据被写入 Elasticsearch,就不会再被修改。
    • 若要更新数据,不会直接在原数据上操作,而是创建一条新的数据记录来替换旧的,旧数据仍然保留在系统中。
// 原始结构(可修改)
{
  "order_no": "20230809123456",
  "status": "shipped",
  "update_time": "2023-08-09T12:00:00"
}

// 优化结构(不可变)
{
  "order_no": "20230809123456",
  "status_history": [
    {
      "status": "created",
      "time": "2023-08-09T10:00:00"
    },
    {
      "status": "shipped",
      "time": "2023-08-09T12:00:00" 
    }
  ]
}

4.2 写入模式改造

  • 事件溯源模式
    在这里插入图片描述在这里插入图片描述

4.3 版本控制优化配置

# 调整索引配置
# 此操作是对名为 "orders"  Elasticsearch 索引进行配置调整,目的是优化索引的性能和功能,以适应特定的业务需求。
# PUT 请求用于更新资源,这里是更新 "orders" 索引的设置。

PUT /orders/_settings
{
    "index": {
        # "refresh_interval" 用于设置索引的刷新间隔。
	        # 索引刷新操作会将内存中的数据刷新到磁盘上,使其可以被搜索到。
	        # 这里将刷新间隔设置为 "30s",即每隔 30 秒进行一次刷新操作。
	        # 降低刷新频率可以减少磁盘 I/O 操作,提高索引性能,但会增加数据的可见延迟,即新写入的数据可能需要更长时间才能被搜索到。
        "refresh_interval": "30s",     # 降低刷新频率
        
        	# "number_of_replicas" 表示索引的副本数量。
	        # 副本用于提高数据的可用性和可靠性,当主分片出现故障时,副本分片可以替代主分片继续提供服务。
	        # 这里将副本数量设置为 0,意味着在写入数据时关闭副本。
	        # 关闭副本可以减少写入时的同步开销,提高写入性能,但会降低数据的冗余性和可用性。在数据写入完成后,可以根据需要再将副本数量调整回来。
        "number_of_replicas": 0,       # 写入时关闭副本
	        
	        # "soft_deletes" 用于配置软删除功能。
	        # 软删除是指在删除文档时,并不立即从磁盘上物理删除文档,而是标记为已删除,以便后续可以恢复。
        
        "soft_deletes": {
            # "enabled": true 表示启用软删除功能。
            # 此功能从 Elasticsearch 7.0 版本开始支持,启用后可以在删除文档时保留文档的元数据,方便进行数据恢复和审计。
            "enabled": true,             # 7.0+ 启用软删除
            
            # "retention_leases" 用于控制软删除文档的保留策略。
            "retention_leases": {
                # "enabled": true 表示启用保留租约控制。
                # 保留租约控制可以确保在指定的时间内,软删除的文档不会被物理删除,以便在需要时可以恢复这些文档。
                "enabled": true            # 保留租约控制
            }
        }
    }
}

5. 生产环境故障恢复实践

5.1 紧急止血方案

# 第一步:限制更新速率
	# 此步骤的目的是对整个 Elasticsearch 集群的索引存储更新速率进行限制,避免因过高的写入速率导致磁盘 I/O 压力过大,影响集群的稳定性和性能。
	# PUT 请求用于更新集群的设置,这里更新的是集群的持久化设置,持久化设置会在集群重启后依然生效。

PUT _cluster/settings
{
    "persistent": {
        # "indices.store.throttle.max_bytes_per_sec" 是一个集群级别的设置参数,用于限制索引存储时每秒允许的最大字节数。
        # 这里将其设置为 "50mb",意味着集群中所有索引在存储数据时,每秒写入磁盘的数据量不能超过 50 兆字节。
        "indices.store.throttle.max_bytes_per_sec": "50mb" 
    }
}

# 第二步:关闭副本加快 merge
	# 此步骤是为了在进行某些操作(如强制合并分段)时,提高操作的速度。因为副本的存在会增加数据同步和处理的开销,关闭副本可以减少这些额外的操作。
	# PUT 请求用于更新索引的设置,这里使用 /_all 表示对集群中的所有索引进行设置更新。
PUT /_all/_settings
{
	    # "index.number_of_replicas" 用于设置索引的副本数量。
	    # 这里将其设置为 0,即关闭所有索引的副本。这样在后续的强制合并分段操作中,就不需要考虑副本数据的同步问题,从而加快合并的速度。
	    # 但需要注意的是,关闭副本会降低数据的冗余性和可用性,在操作完成后,建议根据实际需求恢复副本数量。
    "index.number_of_replicas": 0
}

# 第三步:强制合并分段
	# 此步骤的主要目的是对名为 "orders" 的索引进行分段合并操作,以减少索引中的分段数量,提高查询性能。
	#  Elasticsearch 中,数据是以分段(Segment)的形式存储的,随着数据的不断写入和删除,分段数量会逐渐增多,这会增加查询的开销。
	# 通过强制合并分段,可以将多个小分段合并成较少的大分段,从而提高查询效率。
	# POST 请求用于触发强制合并操作。
	# /orders/_forcemerge 表示对 "orders" 索引执行强制合并操作。
	#?max_num_segments=10 是一个查询参数,指定合并后索引中分段的最大数量为 10

POST /orders/_forcemerge?max_num_segments=10

5.2 长期治理措施

  • 三级更新策略
更新类型频率要求实现方式目标延迟
实时型<1秒应用层直接更新500ms
准实时型1-5分钟Kafka+批量更新3分钟
延迟型>30分钟Logstash聚合更新1小时

5.3 效果验证

  • 优化前后核心指标对比:
指标优化前优化后改善幅度
写入吞吐量19,000/s68,000/s258%
段数量/分片71987%
磁盘IOPS89,00022,00075%
GC停顿时间6.5s/min1.2s/min81%

关键结论与最佳实践

避坑指南

      1. 更新频率红线:单个分片每秒更新不超过50次
      1. 版本数监控:定期检查_version字段的统计分布
      1. 分段健康度:控制每个分片分段数<50,单个分段>100MB
      1. 更新模式选择
      • 单字段更新 → 使用Painless脚本
      • 多字段更新 → 整文档替换
      • 状态变更 → 采用追加模式

终极解决方案

  • Lambda架构实现
    在这里插入图片描述在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/982256.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Baklib内容中台赋能企业智管

内容中台构建全场景智管 现代企业数字化运营中&#xff0c;全域内容管理能力已成为核心竞争力。通过智能知识引擎驱动的内容中台架构&#xff0c;企业能够实现跨部门、多形态数据的统一归集与动态调度。以某制造企业为例&#xff0c;其利用中台系统将分散在CRM、ERP及内部文档…

今天来介绍和讨论 AGI(通用人工智能)

首先介绍&#xff0c;AGI&#xff08;通用人工智能&#xff09;是什么&#xff1f; AGI&#xff08;Artificial General Intelligence&#xff0c;通用人工智能&#xff09;指的是能够像人类一样理解、学习、推理和解决广泛任务的人工智能系统。与目前的AI不同&#xff0c;AGI可…

计算机毕业设计SpringBoot+Vue.js乐享田园系统(源码+文档+PPT+讲解)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

navicat导出postgresql的数据库结构、字段名、备注等等

1、执行sql语句 SELECT A.attnum AS "序号",C.relname AS "表名",CAST ( obj_description ( relfilenode, pg_class ) AS VARCHAR ) AS "表名描述",A.attname AS "字段名称",A.attnotnull as "是否不为null",(case when A…

FPGA开发,使用Deepseek V3还是R1(9):FPGA的全流程(详细版)

以下都是Deepseek生成的答案 FPGA开发&#xff0c;使用Deepseek V3还是R1&#xff08;1&#xff09;&#xff1a;应用场景 FPGA开发&#xff0c;使用Deepseek V3还是R1&#xff08;2&#xff09;&#xff1a;V3和R1的区别 FPGA开发&#xff0c;使用Deepseek V3还是R1&#x…

DeepSeek、Grok 和 ChatGPT 对比分析:从技术与应用场景的角度深入探讨

文章目录 一、DeepSeek&#xff1a;知识图谱与高效信息检索1. 核心技术2. 主要特点3. 应用场景4. 实际案例 二、Grok&#xff1a;通用人工智能框架1. 核心技术2. 主要特点3. 应用场景4. 实际案例 三、ChatGPT&#xff1a;聊天机器人与通用对话系统1. 核心技术2. 主要特点3. 应用…

三、0-1搭建springboot+vue3前后端分离-idea新建springboot项目

一、ideal新建项目1 ideal新建项目2 至此父项目就创建好了&#xff0c;下面创建多模块&#xff1a; 填好之后点击create 不删了&#xff0c;直接改包名&#xff0c;看自己喜欢 修改包名和启动类名&#xff1a; 打开ServiceApplication启动类&#xff0c;修改如下&#xff1a; …

快速生成viso流程图图片形式

我们在写详细设计文档的过程中总会不可避免的涉及到时序图或者流程图的绘制&#xff0c;viso这个软件大部分技术人员都会使用&#xff0c;但是想要画的好看&#xff0c;画的科学还是比较难的&#xff0c;现在我总结一套比较好的方法可以生成好看科学的viso图(图片格式)。主要思…

【前端基础】Day 9 PC端品优购项目

目录 1. 品优购项目规划 1.1 网站制作流程 1.2 品优购项目整体介绍 1.3 学习目的 1.4 开发工具以及技术栈 1.5 项目搭建工作 1.6 网站favicon图标 1.7 网站TDK三大标签SEO优化 2. 品优购首页制作 2.1 常见模块类命名 2.2 快捷导航shortcut制作 2.3 header制作 2.4…

仿mudou库one thread oneloop式并发服务器

项目gitee&#xff1a;仿muduo: 仿muduo 一&#xff1a;项目目的 1.1项目简介 通过咱们实现的⾼并发服务器组件&#xff0c;可以简洁快速的完成⼀个⾼性能的服务器搭建。 并且&#xff0c;通过组件内提供的不同应⽤层协议⽀持&#xff0c;也可以快速完成⼀个⾼性能应⽤服务器…

一文学会Spring

一、Spring简介 Spring的优点 Spring是一个开源免费的框架、容器Spring是一个轻量级的框架&#xff0c;非侵入式的控制反转IOC、面向切面AOP支持事务 Spring是一个轻量级的控制反转(IOC)和面向切面(AOP)的容器 二、IOC 2.1 IOC本质 控制反转IOC&#xff0c;是一种设计思想…

解决Spring Boot中LocalDateTime返回前端数据为数组结构的问题

在Spring Boot开发中&#xff0c;处理日期时间数据是一个常见的需求。Java 8 引入了新的日期时间API&#xff0c;如LocalDateTime&#xff0c;它提供了更强大的日期时间处理功能。然而&#xff0c;在将LocalDateTime对象序列化为JSON时&#xff0c;可能会遇到返回为数组结构的问…

【一个月备战蓝桥算法】递归与递推

字典序 在刷题和计算机科学领域&#xff0c;字典序&#xff08;Lexicographical order&#xff09;也称为词典序、字典顺序、字母序&#xff0c;是一种对序列元素进行排序的方式&#xff0c;它模仿了字典中单词的排序规则。下面从不同的数据类型来详细解释字典序&#xff1a; …

CSDN 1024天 创作纪念日

机缘 还记得那是2022年5月&#xff0c;在上家公司工作时候&#xff0c;意外发现同事在通过CSDN记录一些日常遇到、解决的问题&#xff0c;也会更新一些他擅长领域的知识点&#xff0c;并且收获了不少的粉丝和阅读量&#xff0c;这不由得激起了我的兴趣。也在有空时候&#xff…

用于管理 Elasticsearch Serverless 项目的 AI Agent

作者&#xff1a;来自 Elastic Fram Souza 由自然语言驱动的 AI 代理&#xff0c;可轻松管理 Elasticsearch Serverless 项目 - 支持项目创建、删除和状态检查。 这个小型命令行工具让你可以用简单的英语管理你的无服务器 Elasticsearch 项目。它通过AI&#xff08;这里是 Ope…

机器学习数学通关指南

✨ 写在前面 &#x1f4a1; 在代码的世界里沉浸了十余载&#xff0c;我一直自诩逻辑思维敏捷&#xff0c;编程能力不俗。然而&#xff0c;当我初次接触 DeepSeek-R1 并领略其清晰、系统的思考过程时&#xff0c;我不禁为之震撼。那一刻&#xff0c;我深刻意识到&#xff1a;在A…

< 自用文儿 > DELETED 设置速读 in Ubuntu24

systemctl 和 DELETED&#xff1a; 配置文件&#xff1a; vi /etc/systemd/system/ DELETED.service [Unit] DescriptionV2Ray Service Documentation DELETED Afternetwork.target nss-lookup.target[Service] #Usernobody CapabilityBoundingSetCAP_NET_ADMIN CAP_NET_BIN…

intra-mart实现logicDesigner与forma联动

一、前言 有一个需求&#xff0c;想实现从页面上传一个excel文件&#xff0c;点击提交&#xff0c;就转发给forma模块&#xff0c;然后用户在forma模块里&#xff0c;确认下自动填写的信息是否正确&#xff0c;正确的话就点击保存&#xff0c;存入数据库&#xff1b;不正确的话…

优选算法的智慧之光:滑动窗口专题(二)

专栏&#xff1a;算法的魔法世界​​​​​​ 个人主页&#xff1a;手握风云 目录 一、例题讲解 1.1. 最大连续1的个数 III 1.2. 找到字符串中所有字母异位词 1.3. 串联所有单词的子串 1.4. 最小覆盖子串 一、例题讲解 1.1. 最大连续1的个数 III 题目要求是二进制数组&am…

Harbor端口更改||Harbor端口映射

Harbor端口更改|Harbor端口映射 目标&#xff1a;将端口更改为8930 前言 [rootk8s-node1 harbor]# ls common common.sh docker-compose.yml harbor.v2.5.0.tar.gz harbor.yml harbor.yml.tmpl install.sh LICENSE prepare如上是Harbor的文件目录 更改harbor.yml文件…