亿级流量摩擦出来的 ES 设计和优化套路

Elasticsearch(后文用ES 代替)在一般的业务使用中,往往会基于ES 来构建业务日志系统和业务检索系统,在不同的场景中,对ES的要求也完全不一样,吞吐性能的要求、稳定性的要求、成本的要求、可见性的要求。在业务系统中,往往会都一些要求更加的敏感。

我们在业务开发中,该通过怎么样的姿势去使用ES,来持续保持高稳定、持续迭代的ES,稳健的为业务提供价值呢?

本文将以下的一些模块来展开,来分享下这些年在业务场景中沉淀下来的ES使用的一些姿势与方法论,希望通过本文,可以给大家带来一些借鉴与思考,在技术持续产生业务价值的道路上,添砖加瓦

业务价值介绍

开始正文之前,先介绍下,在我负责的系统中,基于ES 构建了怎么样的业务系统,具备怎么样的业务价值,有怎么样的业务体量。

目前在常见的一些业务系统中,电商系统绝对属于其中的一个大头,在整个电商系统中,基于ES 构建的检索系统会非常多,订单检索、商品检索、地图推荐、日志检索... , 目前我在我负责的系统中,主要是用ES 来构建了商品检索体系,商品检索在电商系统中,也是具备着很重要业务份额

为什么商品搜索重要呢?

可以看下上边的这张图,在电商场景中,用户通过搜索、排序、分类、销量等场景来的购物转换,具备非常高的占比,并且也已经养成了用户这样的购物习惯与心智。 一个高性能的搜索系统就尤其重要了。

在电商中,商品搜索,到底是做什么事情呢? 不管是在现实场景,还是线上的数字虚拟场景中,都离不开 人、货、场 的三角关系。 可以看看下图: 人:用户的强意图 货:商品的数量大 场:场地有限

商品搜索就是解决这样的"人、货、场"的核心痛点并为转化带来增长

提供了哪些业务场景

业务场景主要针对商品上的一系列特征描述: 名称、属性、分组、条码... 来进行各种混合联动检索过滤以及特征排序推荐 方便商户侧进行便利的进行商品管理 用户侧快速的商品检索发现,从而实现搜索的业务价值

玩转了哪些技术流程

ps: 终于要开始一些技术相关点了

在商品检索中呢,往往要通过各种各样的一些特征描述数据来进行检索,这个就导致了它势必要将多张表的数据,来进行异构,异构为一个大的类似宽表,从而提供其丰富的检索能力。

商品的描述信息很多,导致了变动的场景和数据量也很庞大,在这种功能系统中,一般都会通过一些异步的方法来与业务系统解耦,提供触发异构的通知。 业界惯例,采取一些 binlog 监听转换的中间件 比如canal、flink cdc 等来进行触发,然后通过些展开异构,来写入到ES 中。然后在为业务提供其查询能力。

简单流程入下图所示

具备了怎么样的体量

所负责系统中的 ES承载了TB级别的数据, 支撑日均亿级别的高频查询和写入,平均耗时也控制在20ms内。 持续稳健的为业务提供着高效的检索能力与实时的写入同步能力

ES 在业务场景下的使用建议

一般我们在 ES 的使用过程中,会遇到一些问题和业务挑战,这些都是我们在使用 ES 中的核心关注点。 业务研发,在了解 ES 底层逻辑的前提之上,需要进行一些顶层的思维模式和方法论。

本章节会从 ES 在整个业务迭代生命周期着手,从过程 中沉淀的一些思路、方法论来展开:ES 建模与设计、技术限 制与业务边界、业务监控体系、检索准入条件、业务的可扩展 设计等

ES 建模

在现阶段数字化经济的背景下,我们做的就是将物理世界中的概念和逻辑,映射为虚拟数字世界中的流转。在整个映射的过程中,核心的关键点就是建模

在当下阶段,技术层出不穷,工具更新换代,都有其特定的名词和形态。我们常用的一些中间件:ES 、kafka、Redis、Mysql... 等,可谓是"百舸争流" 但是幸运的是,在技术迅速变化的背后,总是存在一些持续成立的原则,这些原则就是被验证,稳固的底层架构抽象谓之模型。 当在开发的路上越过了初级、中级之后,需要从"术" 的层面,来逐渐做一些抽象沉淀、然后体悟其"道" 。

:我们常用的一些工具,中间件,比如 上文说到的:搜索引擎 ES 、消息队列kafka、关系型数据库 Mysql 、 非关系型数据库 Redis 等

:这些系统,背后持续成立的原则,构建系统的底层框架。比如:上述的这些都可以归属为数据密集型服务,从底往上,都会有分布式数据的落地,分区、副本、节点;存储与检索:segment、各种索引;数据模型与查询语言:DSL、SQL、table、index 、docment 等

从术 --> 道 的过程,也是建模和抽象的过程。 在业务研发的过程中,也恰说明了 建模的重要性

言归正传,继续回到ES 建模

或许在学生时代,我或许经历过数据建模的一些流程,基于数据建模的流程,我们来类比下ES 建模,看看是有哪些相同点呢

数学建模 ES建模
模型研究 需求分析、性能分析、场景明确
模型假设 业务限界、ES 限制
模型建立 方案设计、详细设计、业务索引设计、ES物理实体设计
模型求解 开发、测试、验证
模型检验 测试验证、性能压测
模型应用 上线交付

通过数据建模,得到的稳固一时的数据真理、解决实际问题 通过 ES 建模,得到的是稳健的,可持续发展的业务架构系统

接下来,从这些步骤,来看看,我们在使用 ES 过程中,核心的一些关注点有哪些

模型调研

业务分析与评估

业务分析与评估,是我们前置最核心的一步,因为ES 分片,节点,结构等如果要在后期在做调整,可以操作,但是成本会比较高

数据规模

  • 近期数据规模:10G 、100G、1T?
  • 远期数据规模:日均10G的增长、1亿的文档数、未来会达到怎么样的数据量
  • 数据是否具备生命周期:是一直存在,还是会消亡,是否可以通过 hot 、warm、cloud、deleted 等冷热数据来做区分

数据分布特点

  • 时间维度区分:比如我们的业务日志、数据统计,按照时间来建立索引
  • 租户维度:saas型系统中,是否要按照租户做隔离,自定义路由后,是否会出先分布不均的问题
  • 用户维度:是否是按照人维度来做区分
  • 扩散维度:数据是否会n* m 维度扩散,ES 索引结构是多张mysql表的聚合,扩散维度是怎样,是否可以不扩散?
  • ...

场景特点

  • 读多写少:是属于怎么样的场景,是否合适用ES ,以及是否可以承载
  • 写多读少:写多的场景,会导致 es 删除文档过多,过多之后则需要进行一些forcemerge 操作,严重时刻会导致集群的一些故障
  • 时效性:可见性的时效要求
  • 读写QPS: 承载怎么样的QPS
  • ... **健壮容忍度
  • 是否可以降级:当前业务场景,如果在 ES 不可用的状态下是否可以降级,是否有替代方案
  • SLI/延迟
  • 可以允许多久恢复
  • ...

业务限界评估

性能限界 业务体量规模 业务是否允许延迟 是否接受暂时的不一致,最终一致 极端情况下的数据丢失,宕机? 恢复 成本限制

模型假设

容量评估

不谋万世者,不足某一时;不谋全局者,不足谋一域

在 ES 初始选择的时候,就需要考虑到未来的容量规划,因为单节点、分片的容量会有一个建议的值,且具备上限,一旦确定了之后,遇到后续数据增长迅猛的前提下,往往会非常煎熬的去做重分片,集群拆分,会带来比较大压力与焦灼,甚至可能诱发一些故障

关于容量评估,腾讯云 ES 官方也给了这样的一些建议 容量影响因素

  • 副本数量:副本有利于增加数据的可靠性,但同时会增加存储成本。

  • 数据膨胀:除原始数据外,ES 需要存储索引、列存数据等,在应用编码压缩等技术后,一般膨胀10%。

  • 内部任务开销:ES 占用约20%的磁盘空间,用于 segment 合并、ES Translog、日志等。

  • 操作系统预留:Linux 操作系统默认为 root 用户预留5%的磁盘空间,用于关键流程处理、系统恢复、防止磁盘碎片化问题等

    腾讯云-集群规格和容量配置评估

模型设计

索引设计

ES 是基于 Lucene 以倒排索引为基础实现的存储体系,不遵循关系型数据库中的范式约定,也不会被约束, 很灵活强大,往往会有一些出其不意的惊喜,尤其当开启了一些自动映射的时候。 所以,需要在业务层面做好约束 吝啬式设计,若非必要、勿增实体

索引字段 ES 不是 DB,我们的异构 ES 索引 往往是多张表的聚合,在 ES 索引字段创建的过程中,尤其要注意 !只保留关注的字段,不做过多冗余 , 尽量不开启自动映射,如果开启,则要做好内部强约束

数据结构 异构的数据,是需要打平,还是多个索引直接并存 往往异构数据如果打平,则会带来更新上的压力 索引拆分 大索引&多个索引? 多索引配合 业务变更 字段合并,提前预设

模型建立

分片

mapping

多租户隔离

帕累托法则: 80%的高频流量,压力和数据,往往来自于20%的租户。这个在各个系统中也会很轻松的发现这个规律。

在设计的过程中,需要从数据清新、读写、压力均衡等方面入手,来考虑设计租户隔离的事情

业务监控

针对 ES 监控,大多数都已具备非常完善的系统维度的监控,比如:

  • 集群、节点、性能指标监控(cpu、内存、带宽、磁盘、...)
  • index 监控,文档、搜索、删除、线程池等
  • 慢DSL 监控...

其实在常态的系统监控背后,一些业务的核心监控指标体系,才是我们后续做优化以及提供高性能服务的前提保障

  • 业务检索指标体系
  • 端到端的延迟体系
  • 特殊异常码监控体系
  • 读写场景下的业务监控等

ES 在一些非日志场景的检索中,对时效性的要求会比较高,从变更到写入,在到查询。端到端的监控,可以更加敏感的发现一些问题

针对一些搜索行为的监控来详细介入下 搜索类型精细化,警惕平均值 需要基于业务场景,指定指标: 比如在电商商品搜索内,有商品名称的模糊匹配检索、c端分类页搜索、大批量的in查询、等一系列的搜索行为

曾经做过一个优化,平均搜索 耗时 在40ms ,很难优化,后来精细化打点之后,发现名称模糊匹配耗时在300ms ,然后针对其做了 分词优化等一系列的处理,最后稳定在20ms之内

搜索行为监控

B端搜索、C端搜索、其他的一些业务场景,包括数据清洗场景等 可以通过清洗之后的搜索语句模板,来定义业务场景

命中数量区间监控 ES 如同MYSQL,要关注其扫描行数,命中条数越多,很容易发生深度分页的问题,造成cpu 飙升

敏感的异常码监控

比如搜索和写入的4xx reject 信息,scroll 上下文数量等 一旦有预警信息,则大概率是体现在业务有问题的

通过主动业务监控发现潜在问题,高耗时查询,在突发流量下,往往会带来突发的性能问题

准入条件

ES 的搜索能力很强大,所以约束会更加的轻松,不类似于mysql 等关系型数据库。这个就会导致一些不合理的请求,演变为漏洞。比如过长的匹配查询,很多的in 查询等, 就需要业在漏洞之上进行一波拦截,保护ES。 生产发生的大部分cpu 飙升问题,往往可以发现都是因为业务的不合理使用导致的,都可以进行一些拦截的

包括不限于 模糊匹配、精确匹配、分页查询、聚合查询等,视各字开放的功能做好限制

ES 的优化套路

一切抛开业务谈优化都是在耍流氓

整体:客户端、业务服务、DSL、ES缓存、ES-Server、 Lucene

花最核心的精力,用最少的成本,做最大收益的事情

ES优化方法论

1. 上层异常

是否入口没有做好拦截,导致了异常查询透传了。是否是瞬时相同的请求流量的透传 业务这样调用是否合理,是否可以优化,是否业务上有可可规避的方式

2.减少查询

思考是否不必要的查询落到了 ES 中,能否减少?

3. 查询路径优化

ES 的嵌套层级是否太深?是否存在不合理的字段设置,导致了性能过差,索引、字段 是否设置合理 ES 查询三阶段,是发生在那一阶段

4. ES底层逻辑优化

是否可以通过 ES 底层的一些方式优化呢?是否需要调整缓存呢

比如,分词器的修改 ngram-> edge_ngram、docvalue_filed、forcemerge 内核升级优等

5.硬件优化

优化硬件设置(操作系统层参数)或者硬件本身,扩容资源(cpu,内存,IO等)

层次越高, 投入成本越高

ES 优化案例 CASE

CASE1 - 查询QPS 无法达标优化

一个高频次查询的API场景,必须由异构的 ES  提供查询能力 (DB还不具备查询条件),QPS一直居高不下,
随着业务发展,吞吐量已经逐步不能满足业务场景,接口频频限流,为了保护全栈系统,限流也不能放开

分析

css 复制代码
通过分析此业务场景在的高频DSL模板 top高流量租户的查询行为
发现在5h内相同请求调用了8k+,且每晚都需要执行
且此数据在其删除之前,都是不会发生变更的

优化 针对此场景,添加一个时间较长缓存,拦截流量持续透传到ES

收益 峰值QPS 下降至原来的1/6 ES 平均耗时下降至原来的1/2

Tips: 这个优化是属于 ES 优化的那个层次

CASE2 - 查询CPU 、耗时、性能优化

erlang 复制代码
一个场景中,存在多个Terms 查询(上限50个),但是性能不是很好,压测场景下QPS只能达到50
且ES CPU负载已经到了50%,会严重影响业务

猜测推演

markdown 复制代码
TermInSetQuery 耗时占比高

1. 是否可以优化?
2. 是否可以不用到TermInSetQuery
3. 假设验证: 数量少一点试试
4. 求助源码

优化

1。terms 10个一批进行拆分
2。should 进行组装

收益

QPS为原来10倍,CPU稳定在20%

Tips: 这个 ES 优化是在那个层次?

CASE3 - ES 限界条件优化

场景

存在一个场景:某天商户的数据超过了1w多条,跳转最后一页进行一些数据操作,跳转不了,异常了

分析

arduino 复制代码
ES 默认 max_result_window: 10000  。
from size 超过了固定页数,导致被ES限制了,上限可以调整。 
要考虑搜索请求占用堆内存和时间与from + size成正比,且用户的数据也是持续增长的。
此场景还无法接受用滚动分页 页面展示有限,每次翻页跳页在上下5页左右

优化 逆序二分 顺序的排序处于最后一页,把顺序翻转,是否就出现在第一页了呢? 针对输入页码跳页,做下限制,固定窗口范围之内。

CASE4 - 检索命中率优化

场景

makefile 复制代码
案例四: 存在一个场景:需要支持模糊检索,但是最匹配符合的要出现在第一位
用电商规格尺码来举例: L  XL/L   LLL 为了支持模糊检索,分词也用了ngram分词器,步长为1  现在要用L来搜索, 出现在第一个的会是那个?

分析

ini 复制代码
ES机制分析: 
	ES的打分机制为 TF/IDF,然后求所有的和 。导致了出现在第一个的就是LLL TF = (词频 / 文档中所有词的总频次) IDF = log(语料库中文档总数 / 包含该词的文档数 + 1)  

业务分析: 
	该索引体量不大,且数据写入和查询qps都较低 既然是所有总分的合计,是否可以冗余精确查询呢,来增强评分呢?

优化 在检索 DSL 中,加入一层term 精确匹配,计入评分 优化后的评分排序

了解特性,应用特性,在合适的场景下,取得良好的收益

总结-遇到ES 响应慢,负载突增怎么办

并不是一上来就考虑资源不足、考虑扩容,也不仅仅是考虑DSL和索引、底层优化

首先从整体分析

  • 整个链路其他环节是否有异常
  • 从用户发起请求到收到返回结果,整体耗时,在哪些地方慢
  • 优先解决上层问题,比如恶意的传参与拦截等

其次层次分析

  • 确定其他层次没有问题,在回到DSL 层
  • 优化策略是考虑减少查询(DSL层)增加前置缓存拦截
  • 再考虑DSL 优化和索引优化,
  • 最后才是考虑硬件优或者扩容,增加资源投入

最后案例复盘

  • 沉淀为我们各自系统中的方法论和案例库和知道意见
  • 作为后续的一些限制条件或约束条件,在做设计与优化的时候

ES 使用与优化,拆解业务,顶层建模 ,整体思考,逐层下推,熟悉架构,理解原理,关注行业

最后祝大家,汇术成道。在技术领域内经久不衰,持续发力!!!

相关推荐
CoderJia程序员甲5 小时前
重学SpringBoot3-整合 Elasticsearch 8.x (三)使用Repository
java·大数据·spring boot·elasticsearch
东方巴黎~Sunsiny5 小时前
如何优化Elasticsearch的查询性能?
大数据·elasticsearch·搜索引擎
mit6.8246 小时前
[Docker#4] 镜像仓库 | 部分常用命令
linux·运维·docker·容器·架构
NoneCoder10 小时前
命令行工具进阶指南
大数据·elasticsearch·搜索引擎
乌恩大侠11 小时前
了解 Open RAN 架构中的 DU 和 CU
架构
贵州晓智信息科技11 小时前
深入理解 React 架构从概览到核心机制
前端·react.js·架构
W Y11 小时前
【架构论文-1】面向服务架构(SOA)
架构·架构设计
Hello.Reader11 小时前
解析Eureka的架构
云原生·eureka·架构
许苑向上12 小时前
【Elasticsearch】Elasticsearch集成Spring Boot
spring boot·elasticsearch·jenkins
航火火13 小时前
回首遥望-C++内存对齐的思考
c++·面试·架构