- 
            
        
    
    
    
            
    
        
            
            创建者: 
                
                    虚拟的现实,上次更新时间:10月 20, 2025 需要 2 分钟阅读时间 
1. PB 级别数据量场景下的 Elasticsearch 调优
1.1. 硬件与操作系统层面
涉及大量 Pipeline Processor 或分词操作的情况建议选择更多核的 CPU 发挥并发优势
Elasticsearch 是重 I/O 和内存操作的程序,对磁盘和内存有较高的要求。建议使用 SSD 硬盘和本地存储,避免网络传输消耗
Elasticsearch 各项查询操作都非常依赖内存。一部分是 JVM 堆内存上的一些数据结构,另一部分是非堆内存。推荐使用 64G内存的机器,并将 JVM 堆内存的大小限制为 4GB~32GB;JVM 堆内存越小,GC 越快,Lucene 缓存的内存越多,查询性能也就越好。当堆内存小于 32GB 时,JVM 会使用内存对象指针压缩技术来优化性能。一旦内存超过 32GB,则不但会浪费内存而且会导致 CPU 和 GC 的性能降低。
内存交换对 Elasticsearch 来说是显著影响性能的行为,建议配置禁用内存交换,可在 elasticsearch.yaml 中将 bootstrap.memory_lock 参数配置为 true。
1.2. 集群配置层面
推荐配置 3个专有主节点仅执行集群层面的操作。
在一台物理机上建议只部署一个节点,也就是一个 Elasticsearch 进程。
当写入量较大时,集群经常会出现写入进程池满载且抛出异常的情况,可以适当增加集群写入进程池的大小,可配置的参数时 thread_pool.write.size 及 thread_pook.write.queue_size
1.3. 业务操作层面
数据写入应尽量采用 bulk 方式。建议将多条数据批量写入集群中,但也需要限定同一批数据的条数,推荐设置为1000~10000条,避免对网络或发送端产生影响。
业务查询应尽量避免返回文档的所有字段,存在大量返回结果会导致额外的性能损耗。如果需要进行分页查询,应尽量避免深度随机分页。
如果业务查询不关注数据与查询条件的匹配程度,可以使用 query-bool-filter 查询代替 query 查询。
对业务的聚合查询,应避免深度嵌套聚合查询,尤其是有大量 bucket 类型的聚合查询,例如 Terms 聚合或 Filter 聚合会产生大量 bucket ,影响聚合性能。
避免对高基数字段做 Terms 聚合。(如 ip、URL 等)
对于 Ters 查询,如果匹配的字段类型很少,可以通过修改 execution_hint 参数的值来修改 Terms 聚合的执行方式以提升性能。
1.4. 监控和预计指标
硬件和操作系统:CPU、内存、磁盘
集群层面:集群状态、集群的 CPU 利用率、集群的磁盘使用率、集群 JVM 个内存区的使用率、集群 GC 情况、集群索引数、集群分片数、集群未分配分片数、单节点承载的最大数据量
索引层面:索引单分片最大存储容量、索引是否只读
业务层面:读取和写入的平均延迟、读取和写入的拒绝率、每秒写入次数。
2. 预测 Elasticsearch 规模并控制成本
| 节点类型 | 节点类型 | 存储需求 | 内存需求 | 计算需求 | 网络需求 | 节点数量 | 
|---|---|---|---|---|---|---|
| 主节点 | 管理集群状态 | 低 | 低 | 低 | 低 | 最少3个 | 
| 数据节点 | 存储与检索数据 | 极高 | 高 | 高 | 中 |  | 
| Ingest 节点 | 转换输入的数据 | 低 | 中 | 高 | 中 |  | 
| 机器学习节点 | 运行机器学习模型 | 低 | 极高 | 极高 | 中 |  | 
| 协调节点 | 分发请求,合并结果 | 低 | 中 | 中 | 中 |  | 
2.1. 数据节点配置预估
一般从3个维度评估,分别是存储容量、分片数、搜索吞吐量。
存储容量根据以下信息评估:
- 每天将存储多少原始数据
- 数据会保留多少天
- 需要设置多少副本
- 为每个数据节点计划分配多少内存
- 内存与磁盘设定的比例
- 数据膨胀系数:Elasticsearch 需要额外使用倒排索引、列式存储,一般会有10% 的数据膨胀
- 内部任务开销比例:Elasticsearch 需要额外约20%的磁盘空间,用于 segment 合并、translog 存储和运行日志等
- 操作系统预留比例:Linux 默认为 root 用户预留 5% 的磁盘空间
- 预留磁盘警戒比例:一般设置为 15%
- 保留一个数据节点用于容错
假设副本分片的数量为 r,数据膨胀系统为 g,内部任务开销比例为 t,操作系统预留比例为 0,警戒比例为 w,可以通过以下公式计算存储:
存储容量=原始数据量*(1+r)*(1+g)*(1-t)/(1-o)*(1+w)
根据经验值计算,存储容量约为原始数据量的 1.67 倍。根据存储容量,可以通过以下公式评估需要的数据节点数:
数据节点数=ceil(存储容量/单节点内存/内存与磁盘比例)+ 容错数据节点数
| 节点类型 | 存储目标 | 磁盘类型建议 | 内存与磁盘比例 | 
|---|---|---|---|
| 热节点 | 搜索为主 | SSD 大于 200Gbit/s | 1:30 | 
| 温节点 | 存储为主 | HDD 约 100Gbit/s | 1:100 | 
| 冷节点 | 归档为主 | 小于 100Gbit/s | 1:500 | 
腾讯云对冷节点和热节点内存与磁盘比例的经验值分别为 1:480 和 1:96
分片数需要根据业务进行合理配置,可以参考以下信息评估:
- 集群有多少个索引
- 每个索引的主分片和副分片设置的数量
- 索引是否有滚动策略?是按时间滚动还是按存储容量滚动?
- 索引保留的时间
官方建议 1GB JVM 堆内存承载的分片数不超过 20个。
总的数据节点数=ceil(总分片数/(20*单节点内存))
除了存储容量和分片数,还需要考虑搜索吞吐量:
- 期望的每秒峰值搜索次数
- 期望的搜索平均响应时间
- 在每个数据节点上期望有几核 CPU 以及对应的线程数
峰值线程数=ceil(每秒峰值搜索次数*平均响应时间/1000)
线程池大小=ceil((每个节点的物理 CPU 核数*单核的线程数*3/2)+1)
数据节点数=ceil(峰值线程数/线程池大小)
通常可以从以下方面思考如何降低 Elasticsearch 集群的成本
- 业务是否真正需要保留很长时间的数据:Elasticsearch 一般用于存储日志、监控等有时效性的数据,在成本有限的情况下,控制存储容量是降低成本最主要的方法
- 利用 Elasticsearch 索引生命周期管理实现热温冷架构:将历史数据迁移到成本更低的硬件中
- 合理配置压缩算法:例如使用腾讯云 Elasticsearch 优化后的 Zstandard 压缩算法,相对 Lucene 默认的压缩算法 LZ4 可提升 35% 的行式存储压缩性,并且性能相当。
- 合理配置副本分片的数量:如果对数据可用性要求不高,那么可以减少副本分片的数量或将副本分片的数量配置为0
- 根据业务场景合理配置字段的行式存储与列式存储
- 业务是否可以将数据汇总以减少存储容量:数据汇总是将原始数据归档或删除,可保留重要的数据或将数据合并,从而减少存储容量。
3. 数据采样
3.1. 常见的采样策略
常见的采样策略包含以下5种:
百分数采样:根据设置的百分数采样,根据随机算法抽取数据
限流采样:根据限制的数据采样,若超过限制的数量则不采样
状态采样:根据调用链的状态采样,只对指定状态的调用链进行采样,如错误的调用链
延迟采样:根据调用链的耗时采样,只对超过耗时的调用链进行采样,例如慢调用
染色采样:根据调用链设置的 tag 采样,只对包含指定 tag 和其对应值的调用链进行采用,如灰度发布时的调用链
在不同的场景下,对系统有不同的采样需求,例如以下的几种场景:
- 降低系统损耗
- 对错误调用链路的全量采集
- 对慢调用的全量采集
- 对特殊请求的全量采集
基于 QPS 的自适应采样结合错误调用全量采样、慢调用全量采样、特殊请求全量采用来设计,需要预先设置以下的采样参数:
采样最小阈值:在 QPS 小于 QPS 设定的最小阈值的情况下,采样率为 100%,对低吞吐量的应用链路进行全量采样。例如,将最小 QPS 设置为100,每秒收到的请求数小于 100 的应用产生的链路信息会被全部采样。
采样最大阈值:在 QPS 大于阈值的情况下,当超过最大阈值时,采样率为0。即在高并发场景下,超过一定数量的请求直接不采样,消除链路组件对应用性能的影响,确保业务稳定运行。例如,将最大 QPS 设置为 10000,则每秒请求数大于10000的应用在超过 10000 之后的调用信息将全部丢弃
采样百分数:在 QPS 大于最小阈值且小于最大阈值的情况下,采样率为设置的百分数。例如,将采样百分数设置为10%,采样 QPS 最小阈值为100,采样 QPS 最大阈值为 10000,该应用最大采样率为 10000*10%,最小采样数为 10。
慢调用阈值:在配置了慢调用阈值的情况下,无论采样的 QPS 阈值和采样百分数设置为多少,都会对超过慢调用阈值的链路信息进行采集。如果慢调用阈值为 10秒,那么超过10秒的调用链都会被采样。
错误回溯采样:在启用错误回溯采样的情况下,无论采样的 QPS 阈值和采样百分数设置为多少,都会对错误的调用链路进行采样。错误回溯采样并不完全是单元采样,而是可以在产生错误的服务的上游同时感知到该错误,并对上游的链路也进行采样。
染色采样 tag:在配置了染色采样 tag 的情况下,无论采样的 QPS 阈值和采样百分数设置为多少,都对带有该 Tag 的链路进行采样。
3.2. 链路采集方案对比
| 项目 | OpenTelemetry | SkyWalking | Spring Cloud Sleuth | 
|---|---|---|---|
| 数据协议 | OTLP,支持 ZipKin、Jaeger 协议 | 遵循 OpenTracing 规范,Segment 包含 span | 底层为 Zipkin ,遵循 OpenTracing | 
| 语言支持 | Java\Go\Python\JavaScript\C++\.NET \Erlang\PHP\Ruby\Rust\Swift | Java\Python\LUA\Kong\JavaScript\Rust\PHP | Java | 
| 组件和框架支持 | MySQL\Redis\Kafka\Spring\Dubbo\Netty | MySQL\Redis\Kafka\Spring\Dubbo\Netty | Spring Cloud 框架 MySQL\Redis\Kafka\Netty | 
| 采集方式 | SDK\Agent | SDK\Agent | SDK | 
| 采集的颗粒度 | 接口级埋点 | 接口级埋点 | 不支持接口级埋点 | 
| 数据上报方式 | HTTP\Zipkin\Jaeger | gRPC\Zipkin | HTTP | 
3.3. 链路采集性能对比
| 指标 | OpenTelemetry | SkyWalking | Spring Cloud Sleuth | 
|---|---|---|---|
| 采样率 | 100% | 100% | 100% | 
| 线程数/个 | 10 | 10 | 10 | 
| 请求总数/个 | 100000 | 100000 | 100000 | 
| 每秒请求数/秒 | 6267.06 | 5883.37 | 6392.10 | 
| 平均请求时间/秒 | 0.159 | 0.170 | 0.156 | 
| 最大请求时间/个 | 17 | 85 | 21 | 
| P50/秒 | 1 | 2 | 1 | 
| P75/秒 | 2 | 2 | 2 | 
| P95/秒 | 2 | 2 | 2 | 
| P99/秒 | 4 | 7 | 4 | 
- 无标签
0 评论