电商场景下 ES 搜索引擎的稳定性治理实践

继上文在完成了第一阶段 ES 搜索引擎的搭建后,已经能够实现对千万级别的商品索引的读写请求的支持。目前,单机房读流量在 500~1000 QPS 之间,写流量在 500 QPS 左右。

但随着业务的发展,问题也逐渐开始暴露,起源是在某次活动下线的时候,ES 集群某个机房 CPU 迅速被打满,读延迟上升,而其他机房却是正常的,之后仍然出现了多次 CPU 暴涨,多个机房的其中一个机房被打满或者同时打满的情形,然而读写流量波动却不大或者根本不及日常峰值。我们意识到此时出现的就是 ES 集群的性能问题,在第一阶段当系统依赖组件不可用时,为此系统拥有一定的容灾能力,暂时没有考虑业务使用姿势带来的风险,而这种风险是更可怕的,源于它随机,毫无规律,不可控制。

在此情况下,也许大家会考虑通过扩容来解决问题,但当前情况已经是在我们扩容后发生的问题了,所以很明显此时扩容已经解决不了问题了。程序员经常说的几句表达风险等级的话:

  • 阶段一:不知道自己不知道(Unconscious incompetence)

  • 阶段二:知道自己不知道(Conscious incompetence)

  • 阶段三:知道自己知道(Conscious competence)

  • 阶段四:不知道自己知道(Unconscious competence)

用在此时就是阶段一和阶段二,不知道自己不知道,所以也就无法在业务风险控制这里发力,当问题出现后,知道了自己不知道,但不知道发生了什么,不知道为什么会发生,不知道还会发生什么。看似充满随机性,但实际上却是一个很严肃的问题,招商平台对大促活动非常重要,由此也引发了我们新的思考,我们做 ES 稳定性的全局视角是什么,该怎么定义和归类?这些思考也为后续的治理提供了更好的解决思路和发现问题的角度。

治理思路

ES集群读写链路图

在治理思路中我们仍然从系统读写两个入口入手,分别细化读和写链路应该考虑的问题和风险以及需要达到的业务目标,下文将从具体的实施步骤进行介绍。

治理的目标是什么

治理目标有两个,分别是系统的可用性、稳定性和数据质量,系统可用性指的是稳定提供读写能力,数据质量即保证 ES 的数据和源数据完全一致,并且延迟符合业务预期,达到不仅有数据而且是有质量的数据标准。

如何量化目标

在量化目标中,系统可用性沿用了 ES 集群 SLA 进行衡量可用性。数据质量可以理解为数据最终一致性和数据延迟,目前我们核心的数据包含准实时数据流,报名记录 DB->ES,商品比价通过文档数据库->ES,并需要定时更新指标。DB->ES 设定的目标是 30s 内的一致率在 99.9% 以上,通过准实时对账进行监控报警监测。

随着商品控价越来越重要,比价的数据筛选和查询也尤为重要,文档数据库->ES 设定的是不存在超时小时级别的同步延迟,且将定时更新指标定为 T+1。

如何达成目标

原则:自上而下,逐层拆解,彼此独立,互为补充。

优化措施

此时回顾一下,上节我们提到的 ES CPU 暴涨问题最后是如何解决的?实际上,我们并没有走捷径,而是将 ES 读链路全部梳理了一遍,分析每次 CPU 暴涨的流量差异点。之前的分析仅仅是从 ES 集群监控上分析不同索引的流量趋势,由于差异点太小,无法进行有效分析。因此,我们仍然需要先完善监控报警机制,将 ES 上层的云引擎服务的接口流量监控全部聚合在一个监控看板上,并加入了 API /中间 RPC 层--> 数据中心 RPC 服务--> ES,从而找到了问题的突破口。我们发现,CPU 上涨的点 Scroll 流量偏高,因为 Scroll 流量比 Search 流量更耗 CPU,因此 Scroll 流量会被打满。在明确原因之后,我们也就开启了 ES 性能的优化之路。

为什么 ES Scroll 流量比 Search 流量更耗 CPU?

  1. Search 查询有数据缓存而 Scroll 没有:在Search API 中,ES 会执行查询并返回匹配的结果集。这些结果通常是直接从索引中检索的,并且在查询时可能会使用缓存来提高性能。一旦查询完成,ES 会将结果缓存在内存中,以便稍后进行排序、分页等操作。这样,在后续的请求中,如果只需要访问缓存中的数据,可以避免重新计算和访问磁盘,从而减少了 CPU 的消耗。相比之下,Scroll API 在处理流量时不会使用缓存。它的工作方式是创建一个游标(Cursor),并在服务器端维护一个快照,以便在后续的请求中能够继续从上一个请求的位置继续返回结果。这意味着每次请求都需要重新计算和访问磁盘上的数据,并且不能利用缓存。这会导致更多的 CPU 计算和磁盘访问,从而增加了 CPU 的消耗。

  2. Search 是无状态查询,Scroll 需要上下文维护:Scroll API 需要维护上下文信息,以便在后续的请求中能够正确地返回结果。这个上下文信息可能包括游标位置、排序信息、过滤条件等。为了保持这些上下文的一致性和完整性,ES 需要在服务器端维护和更新相关的状态。

  3. 这不意味着 Scroll API 一定比 Search API 更耗 CPU。实际的 CPU 消耗还受到多个因素的影响,包括查询的复杂性、数据量的大小、硬件配置等,需要结合实际情况观测。

ES 查询链路治理

将 ES 不合规的 Scroll 流量全部迁走

在某次大促活动之前,招商平台提供的某个活动下报名记录的全量获取接口走的全是 ES Scroll 流量,基本维持在 100+ QPS 水平,大多场景用于离线对账和首次数据拉取,我们通过跟业务沟通改离线对账或者走 DB 查询等方式,把不合理的 Scroll 查询迁移走。迁移了 Scroll 请求约 30+ 业务方, QPS 从 100+ 降到个位数,基本解决了 Scroll 场景的性能隐患。

ES 慢查询治理

慢查询是一个相对的概念,不是一个绝对的概念,不是说某种查询一定是慢查询,或者某种查询一定不是慢查询,他和数据规模等因素相关性很大。大多都是因为实现方式的原因,他的慢会随着数据规模增长而逐渐明显,所以支持亿级数据量和万级、百万级完全不是一回事,不到一定数据量,同样的实现可能也并不会产生问题。

在大规模数据场景下,慢查询的慢会越发明显,往往慢查询几十的 QPS 就能占用正常查询上千 QPS 所需要的资源。在其它流量突然增加的情况下,一般慢查询的耗时会成倍增加,也意味着它占用的资源一直得不到释放,给系统带来巨大的性能隐患。下面举例说明一些观察到的 ES 慢查询:

  1. Terms 查询在每次查询的数量过大时都会导致慢查询,系统当时存在每次 Terms 查询 万个商品的场景,耗时在 1s+,商品写流量进来后,查询耗时翻好几倍,CPU 被打满。

  2. 对 Double 类型字段做 Term 查询,因为检索方式和数据结构不匹配,同样还是因为数据量过大,导致慢查询。

  3. 高区分度字段 Terms 聚合。

慢查询的规避手段也已经相对比较成熟。可以完善慢查询的监控报警机制在 CPU 使用率是偏高时制定合理的报警阈值。借此我们也梳理了 ES 查询可能存在的慢查询 Case,排查其他业务隐患,由此慢查询带来的 CPU 上涨问题也已经被排查解决。

Range 查询优化

缓存是提升 ES 查询性能的重要手段,如果查询缓存命中率低,则可以定向优化。ES Filter 查询的时候会缓存查询频次较高的请求结果,然而 Range 查询的特殊点在于,如果每次查询的时间区间不一样,会导致一直缓存,然而命中率极低,引发系统频繁 GC,从而造成稳定性问题。

优化方法:

  1. Range 查询走普通查询,不通过 Filter 过滤器缓存。

  2. 优化 Range 查询,比如指定时间区间查询,提高分片维度请求缓存命中率,并降低缓存频繁构建和垃圾回收频率。仅查询需要的字段

在我们的系统中就曾出现过获取活动列表活动的配置非常大,流量变高时迅速把 CPU 打满的问题。主要因为 ES 查询默认是 query_then_fetch 模式,如果业务的索引文档比较大,每次查询都返回整个索引文档的话,那么 Fetch 的耗时就会变高,造成慢查询,或者内存被打爆的情况,所以仅查询需要的字段可以节省带宽,和磁盘访问耗时,从而提升查询效率。

ES 写入链路治理

仅写入需要索引的字段

ES 的定位是搜索和统计,所以我们在后面的治理中也是非常谨慎对待需要写入 ES 的字段,仅写入索引和统计字段,其它数据则可以回表查询,该方式可以避免索引膨胀速度过快,影响查询和索引重建效率,也是更多资源的浪费。

Nested 索引优化

索引通常会面临父子文档关联文档这样的查询场景,有的还要求子文档能够独立搜索,Nested 类型就是 ES 帮甲方解决此类问题的。Nested 其实是非常好的一个设计,性能也很优越,但它的前提是子文档不能太大,子文档深度不能太深,文档膨胀相对可控,查询方式友好,总之大数据规模使用 Nested,需要多加前提,能不用就不用,小数据规模就不用太有负担。

Nested 的查询和索引性能都稍逊于普通索引类型,通常是普通索引好几倍的资源消耗,我们为了解决商品索引 SPU->SKU Nested 慢查询问题,以及降低索引膨胀速度,通过将 ES 的 SKU Nested 索引设置为 Object 类型,并且把 SKU 维度的信息计算结果作为 SPU 字段共同提供简单查询,满足业务查询需要,这样我们既做到了业务无损,也降低了系统压力。通过以上优化我们的写入膨胀系数降低了 20 倍左右,文档数从 40 亿缩减到了 2 亿,并通过压测佐证写入性能提升了 20%+,也不会再高频出现该类慢查询的情况。

消息乱序问题

RocketMQ 乱序问题:

  1. 通过 Client SDK 发送数据时,如果发送失败则会快速重试发送到其它 Queue,此时同一个 Key 的消息在不同的 Queue 中造成消息乱序到达 ES;

  2. RocketMQ 如果出现发生 Rebalance,可能会导致同一组消息同时给多个消费者消费,从而发生 ABA 覆盖写问题。

以上都会造成丢失更新的问题,所以需要利用 RocketMQ 来保证有序性,但也并不能达到 100% 的效果。我们在比价消费场景中就曾遇到问题,一个报名商品有 N 个 SKU,会分别进行站内外比价,以及自身比价结果计算,基本上都是并发进行的,这就导致多个比价结果在同一时刻到达,其中一个消息在写入时发生失败自动重试写入到其它 Queue,即发生了比价消息更新覆盖的问题。在具体的解决过程中我们设计了如下三个方案:

  1. 采用比价的 Version 乐观锁控制,采用 Script+Verison 写,但是由于 Script 的写入性能不高,而且比价目前的写入流量最高 2k+,未来随着商品量级增加会更多,所以未采用。

  2. 采用 ES 的 Version 版本号控制,写入时带上 Version 版本号,但是因为前面介绍过我们的一条报名记录会有多个写入入口,全局 Version 版本号的形式成本太高,也未采用。

  3. ✅ 采用批量聚合消费的方式。即 FaaS 单条消费改为批量消费,按照最大消息数或者聚合时间消费聚合,这样可以处理单条消息并发更新的 Case。采用该方式首先因为改动成本低,本身的 SDK 也能够支持,可以聚焦解决问题,少量 Case 依然使用对账 T+1 补偿的方式。

ES 资源隔离

目前我们的 ES 集群承载着所有招商需要的 ES 索引的流量,包括活动、企划、报名实体索引等,目前的稳定性保障预期总读流量可以支持 2000+ QPS,写流量 6000+ QPS。然而在压测时使用线上真实流量压测,我们在分别压读、压写,同时压读和写,通过控制变量的方式压测时发现读流量的资源倾斜非常严重,部分节点的 CPU 使用率很高,整体压不上去。通过分析后发现是因为不同索引的分片分布不一样导致的,所以读写流量分布不均,并且不同索引的重保等级是不一样的,介于此原因,我们认为资源隔离可以更好的规避风险,提高系统可用性,根据不同的分片分布特性,分配不同的 ES 集群规格,也有利于资源使用率最大化。

治理效果

  1. ES 集群资源使用情况符合预期,不再出现 CPU 暴涨、CPU 被打满、持续慢查询情况,基本解决了非预期的 CPU 增长问题,系统性能保持稳定。

  2. ES 索引文档数从 40 亿缩减到 2 亿+,ES 写性能提升 20%+,写入 QPS 最高可支持 1w+,性能上可以超出业务需求满足业务使用。

当然在每次活动之前,我们也都会结合稳定性的治理 House 来分析容量变化、流量变化、监控报警,并根据需求定向优化以上几个方面,保证每一次的系统变化都在预期范围内,把一切不确定因素变得确定。当然在未来的实践中仍需不断探索,挖掘 ES 在实践能力上的更多可能性。

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

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

相关文章

Qt篇——QChartView获取鼠标停留位置的数值

需求:鼠标停留在QChartView上时,想要计算停留位置的数值。 一开始的方法是想要通过鼠标移动事件计算鼠标在QChartView上的坐标,在换算成数值,后来发现QChartView中除了图表数据,还有坐标轴与坐标轴数值标签占了高度&a…

采购代购系统独立站,接口采集商品上货

采购代购系统独立站的建设与商品上货接口的采集是一个综合性的项目,涉及前端开发、后端开发、数据库设计以及API接口的对接等多个环节。以下是一个大致的步骤和考虑因素: 一、系统规划与需求分析 明确业务需求:确定代购系统的核心功能&…

智能物流新纪元:分布式I/O模块重塑仓储自动化

随着工业4.0概念的深入人心,物流行业正在经历前所未有的变革。在这个过程中,物流企业必须积极走向工业自动化、智能化,进而提高物流效率,降低物流成本,以便更好地满足客户和市场的需求。智能物流、仓库自动化已然是趋势…

SSM整合项目(Vue3环境搭建)

SSM整合项目(Vue3环境搭建) 1.下载node.js 1.卸载原来的node.js 2.检测是否卸载成功 3.下载node.js(10.16.3) 一路next就可以 4.检测是否安装成功 2.全局安装Vue插件cli 命令行输入 npm install -g vue/cli 3.新建Vue项目 1.…

惬意上手MongDB

上一篇文章介绍了MySQL,今天来介绍一下MongoDB,相较于MySQL而言,它是简单的。 简介 MongoDB是一种开源的、跨平台的文档数据库,采用NoSQL数据库的形式。它以高性能、高可用性和灵活的数据模型而闻名,适用于大规模数据存储和处理…

html--钢琴

代码 <!DOCTYPE html> <html> <head> <meta http-equiv"Content-Type" content"text/html; charsetutf-8" /> <title>html钢琴</title> <script src"js/js.js"></script> <link href"…

QT开发(二) 构建QMainWindow

1、前言 QMainWindow是Qt框架中用于创建应用程序主窗口的类。它是许多GUI应用程序的基础&#xff0c;提供了丰富的功能和灵活性&#xff0c;以支持用户界面的创建和管理。 QMainWindow的结构主要包括以下几个部分&#xff1a; 菜单栏&#xff08;Menu Bar&#xff09;&#…

【单调栈】代码随想录算法训练营第六十天 |84.柱状图中最大的矩形(待补充)

84.柱状图中最大的矩形 1、题目链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 2、文章讲解&#xff1a;代码随想录 3、题目&#xff1a; 给定 n 个非负整数&#xff0c;用来表示柱状图中各个柱子的高度。每个柱子彼此相邻&#xff0c;且宽度为 1 。 求在该柱…

RC4算法:流密码算法的经典之作

title: RC4算法&#xff1a;流密码算法的经典之作 date: 2024/3/11 18:16:16 updated: 2024/3/11 18:16:16 tags: RC4起源演变算法优劣分析RC4 vs AES安全性RC4 vs DES性能比较应用场景介绍工作原理详解代码实例演示 一、RC4算法的起源与演变 RC4算法是由著名密码学家Ron Riv…

粒子群算法对pi控制器进行参数优化,随时优化pi参数以控制直流无刷电机转速。

粒子群算法对pi控制器进行参数优化&#xff0c;随时优化pi参数以取得设定直流无刷电机转速。 PSO优化PID&#xff0c;用于BLDC速度控制 仿真平台为&#xff1a;MATLAB 采用的是Simulinkm程序相配合 仿真结果以及程序示例&#xff1a;

UnityShader常用算法笔记(颜色叠加混合、RGB-HSV-HSL的转换、重映射、UV序列帧动画采样等,持续更新中)

一.颜色叠加混合 1.Blend混合 // 正常&#xff0c;透明度混合 Normal Blend SrcAlpha OneMinusSrcAlpha //柔和叠加 Soft Additive Blend OneMinusDstColor One //正片叠底 相乘 Multiply Blend DstColor Zero //两倍叠加 相加 2x Multiply Blend DstColor SrcColor //变暗…

一款前端开发工具Hbuilder

背景&#xff1a;最近日在接触前同事留下的一个VUE项目&#xff08;只有前端代码&#xff0c;后台服务压根没写真不知道以前是怎么糊弄过去的&#xff09;时&#xff0c;发现一款可以快速开发前端的软件&#xff1b;今日分享一下。 当我打开项目时发现&#xff0c;有个app.vue…

C语言——详解字符函数和字符串函数(一)

Hi,铁子们好呀&#xff01;今天博主来给大家更一篇C语言的字符函数和字符串函数~ 具体讲的内容如下&#xff1a; 文章目录 &#x1f386;1.字符分类函数&#x1f4af;&#x1f4af;⏩1.1 什么是字符分类函数的&#xff1f;&#x1f4af;&#x1f4af;⏩1.2 字符函数的类型有哪…

回归预测 | Matlab实现GSWOA-KELM混合策略改进的鲸鱼优化算法优化核极限学习机的数据回归预测

回归预测 | Matlab实现GSWOA-KELM混合策略改进的鲸鱼优化算法优化核极限学习机的数据回归预测 目录 回归预测 | Matlab实现GSWOA-KELM混合策略改进的鲸鱼优化算法优化核极限学习机的数据回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 GSWOA-KELM多变量回归预测…

ffmpeg解码和渲染理解

ffmpeg解码和渲染理解 ffmpeg视频解码步骤 FFmpeg 是一个功能强大的跨平台多媒体处理工具&#xff0c;包含了音视频编解码、封装/解封装、过滤器等功能。下面是一般情况下使用 FFmpeg 进行视频解码的步骤&#xff1a; 初始化 FFmpeg 库&#xff1a;首先需要初始化 FFmpeg 库&a…

linux系统达梦数据库(安装及操作)

新建 dmdba 用户 注意: 安装前必须创建 dmdba 用户&#xff0c;禁止使用 root 用户安装数据库。 创建用户所在的组&#xff0c;命令如下&#xff1a; groupadd dinstall 创建用户&#xff0c;命令如下&#xff1a; useradd -g dinstall -m -d /home/dmdba -s /bin/bash dmdba 修…

一文彻底搞懂OSI七层模型和TCP/IP四层模型

文章目录 1. OSI七层模型2. TCP/IP四层模型 1. OSI七层模型 OSI&#xff08;Open System Interconnect&#xff09;七层模型是一种将计算机网络通信协议划分为七个不同层次的标准化框架。每一层都负责不同的功能&#xff0c;从物理连接到应用程序的处理。这种模型有助于不同的…

口才提升秘籍:马云的说话之道你也能学会!

口才提升秘籍&#xff1a;马云的说话之道你也能学会&#xff01; 在商界&#xff0c;马云以其卓越的领导才能和出色的口才赢得了广泛的赞誉。他的每一次演讲都充满智慧和力量&#xff0c;不仅激发了员工的斗志&#xff0c;也赢得了合作伙伴的信任。那么&#xff0c;马云是如何…

ctf杂项总结

1.文件无法打开 1.1.文件拓展名损坏/错误导致 方法&#xff1a; 1.使用kali当中的file命令查看&#xff0c;之后修改为正确的后缀即可 2.通过16进制编辑器打开查看文件头 3.文件头残缺/错误&#xff0c;可以先使用kail当中的file命令查看它的类型&#xff0c;之后再通过 16…

基于springboot实现驾校信息管理系统项目【项目源码+论文说明】

基于springboot实现驾校信息管理系统演示 摘要 随着人们生活水平的不断提高&#xff0c;出行方式多样化&#xff0c;也以私家车为主&#xff0c;那么既然私家车的需求不断增长&#xff0c;那么基于驾校的考核管理也就不断增强&#xff0c;那么业务系统也就慢慢的随之加大。信息…