OpenSearch 2.4.0 版本技术解析:PIT 点查、加权分片路由与搜索背压机制全解读
【免费下载链接】OpenSearch🔎 Open source distributed and RESTful search engine.项目地址: https://gitcode.com/gh_mirrors/op/OpenSearch
导读
本文基于 OpenSearch 官方发布的 2.4.0 Release Notes(release-notes/opensearch.release-notes-2.4.0.md,发布于 2022-11-04),系统梳理该版本引入的核心新特性——Point in Time(PIT)搜索、实验性可搜索快照、区域退役/恢复与加权分片路由、专用 search 节点角色、搜索背压(Search Backpressure)资源追踪等,并结合当前仓库源码逐项印证其底层实现与配置方式。读完本文,你将掌握 2.4.0 各新增功能的适用场景、关键配置参数、默认值与源码落点,并了解该版本在稳定性修复、依赖升级与安全(CVE)方面的完整变更清单。
版本概览
OpenSearch 2.4.0 于 2022 年 11 月 4 日发布,是 2.x 系列中功能密度较高的一次迭代。本次版本的核心主题可以概括为三条主线:
- 搜索体验与成本优化:引入 Point in Time 搜索(后续 SQL/PPL 插件查询能力的基础)、实验性可搜索快照、专用 search 节点角色,让大规模只读/冷数据场景具备更经济、更稳定的查询方案;
- 集群路由与可用性:新增区域退役(decommission)/恢复(recommission)API 与加权分片路由策略,配合段复制(Segment Replication)故障转移支持,增强多可用区部署下的容错与流量调度能力;
- 稳定性与安全加固:引入基于资源消耗的 SearchShardTask 在途取消机制与搜索背压统计 API,同时修复大量 Windows 启动脚本、恢复、复制相关的缺陷,并升级依赖以缓解多个 CVE。
以下按 Release Notes 的 Added / Changed / Removed / Fixed / Security / Dependencies 结构展开,并在每个小节补充仓库源码级佐证。
核心新增功能(Added)
1. Point in Time(PIT)搜索
Introduce point in time search feature是 2.4.0 最重要的功能之一。PIT 允许搜索请求基于某个时间点创建的"固定"数据快照上下文执行,而不是基于最新的 reader 上下文,从而为跨请求的一致性查询(如分页、滚动、SQL 聚合)提供稳定视图。
从源码看,PIT 的请求载体定义在 PointInTimeBuilder.java,其 javadoc 明确指出:
A search request with a point in time will execute using the reader contexts associated with that point time instead of the latest reader contexts.
该类对外暴露两个核心字段:
| 字段 | 类型 | 说明 |
|---|---|---|
id | String | PIT 的唯一标识,创建 PIT 时返回,搜索时必须携带 |
keep_alive | TimeValue | PIT 的存活时间;若在搜索请求中再次指定,可延长该 PIT 的保留时长 |
该 Builder 实现了Writeable与ToXContentObject,意味着它既能在节点间通过 Stream 传输,也能以 JSON 形式出现在搜索请求体与响应中;解析时若缺少id,会抛出IllegalArgumentException("point int time id is not provided")。keep_alive通过TimeValue.parseTimeValue解析,支持如1m、30s等标准时间单位字符串。
PIT 的创建流程由 CreatePitController.java 负责,采用两阶段提交设计:
- 阶段一:在相关分片上以临时 keep-alive 创建 PIT reader 上下文;
- 阶段二:将 PIT ID 与请求中的 keep_alive 写入上下文,若任一分片更新失败则清理已创建的 PIT。
这种两阶段设计是为了把 PIT ID 保存进上下文本身,便于后续的 List PIT、Delete PIT 等管理能力复用。该控制器同时定义了PIT_INIT_KEEP_ALIVE正向时间设置,用于控制创建阶段的临时存活时长。
从源码结构还可以看到,PIT 能力贯穿 SearchRequest.java、SearchSourceBuilder.java 与 SearchTransportService.java 等多个搜索链路核心类,是搜索层的一等公民,而不仅仅是独立接口。
2. 实验性可搜索快照(Searchable Snapshot)
Introduce experimental searchable snapshot feature让索引可以直接从快照仓库(如 S3、GCS 等远程对象存储)中搜索,无需先将全部数据恢复到本地磁盘。该特性在 2.4.0 中仍处于实验阶段。
从当前仓库源码可以印证其基础设施已经就位:server/src/main/java/org/opensearch/index/store/remote包下存在directory(远程目录实现,如BlockUnpinningDirectory)、filecache(本地文件缓存)等模块,FileCacheSettings.java 提供了文件缓存相关配置;IndexSettings.java 中登记了与远程存储/快照相关的索引级设置。与"远程存储(Remote Store)"体系结合后,可搜索快照的典型收益是:只读冷数据可以直接挂载快照进行搜索,显著降低存储成本。由于是实验特性,生产使用前务必查阅对应版本的官方文档与特性开关说明。
3. 区域退役/恢复 API 与加权分片路由(Weighted Zonal Search Request Routing)
Add API for decommissioning/recommissioning zone and weighted zonal search request routing policy是为多可用区(zone)部署设计的路由治理能力,包含两大部分:
- 区域退役(decommission)/恢复(recommission):运维上可以将某个 zone 整体标记为退役状态,让分片与流量逐步迁出该 zone;恢复操作则反向放行。
- 加权分片路由(weighted shard routing):按节点属性(attribute)与权重分配搜索流量,实现对不同 zone 或不同规格节点的差异化流量调度。
加权路由的数据模型定义在 WeightedRouting.java(标注@PublicApi(since = "2.4.0")),其核心是"属性名 + 权重表":
public WeightedRouting(String attributeName, Map<String, Double> weights) { this.attributeName = attributeName; this.weights = Collections.unmodifiableMap(weights); ... }即:attributeName指定节点属性(例如zone),weights为该属性各取值(例如各 zone 名称)到权重(0~1 之间的浮点数)的映射。isSet()方法要求属性名非空且权重表非空,否则视为未启用。
2.4.0 同时补齐了该能力的 PUT / GET / DELETE 三套 REST API(对应 TransportAddWeightedRoutingAction.java、TransportGetWeightedRoutingAction.java、TransportDeleteWeightedRoutingAction.java,REST 层入口见 RestClusterPutWeightedRoutingAction.java),并在 WeightedRoutingMetadata.java 中持久化到集群元数据。Release Notes 中"Fix weighted routing metadata deserialization error on process restart"表明该元数据序列化/反序列化在进程重启场景下已做加固。
调度侧,WeightedRoutingService.java 与 OperationRouting.java 配合实现加权选择逻辑,同时引入 FailAwareWeightedRouting.java、NodeWeighedAwayException.java 等辅助类——当某节点被"加权排除"(权重为 0 或失败计数触发)时会抛出NodeWeighedAwayException走重试路径,保证路由决策的健壮性。
4. 专用 search 节点角色
Add a new node role 'search' which is dedicated to provide search capability引入了专职搜索节点角色。在 DiscoveryNodeRole.java 中,该角色定义为:
public static final DiscoveryNodeRole SEARCH_ROLE = new DiscoveryNodeRole("search", "s", true) { ... };关键约束在validateRole方法中:search 角色不能与任何其他角色组合在同一节点上,违反时抛IllegalArgumentException。这意味着 search 节点是纯搜索型节点,配合副本分片承载只读查询流量,从而隔离搜索负载与写入/管理负载。同一版本中一并出现的还有 warm 角色(源码注释明确"warm role is added in 2.4"),用于承载 warm 索引。配置方式是在opensearch.yml中通过node.roles声明,例如仅保留search一项。
5. 远程 translog 特性开关(Remote Translog Feature Flag)
Introduce Remote translog feature flag将远程 translog(remote translog,配合远程存储体系将 translog 持久化到对象存储)以**特性开关(feature flag)**形式引入,方便逐步验证与灰度。从当前仓库看,远程存储相关能力已广泛分布在 IndexMetadata.java、IndexSettings.java、RemoteStoreRestoreService.java 及server/src/main/java/org/opensearch/gateway/remote包(RemoteClusterStateService、RemoteIndexMetadataManager、RemoteManifestManager 等)中,feature flag 的注册集中在 FeatureFlags.java 与 FeatureFlagSettings.java。
2.4.0 还在远程存储方向做了多项配套变更,例如 "Use RemoteSegmentStoreDirectory instead of RemoteDirectory"、"Add index specific setting for remote repository"、"Change behaviour in replica recovery for remote translog enabled indices",共同把远程存储的 segment 目录抽象、索引级仓库配置与副本恢复路径推向成熟。
6. 段复制(Segment Replication)故障转移支持
Add failover support with Segment Replication enabled完善了段复制模式下的故障转移链路。段复制是 OpenSearch 为降低主分片网络/IO 开销而设计的复制模型(副本直接拉取主分片已提交的 segment 文件,而非复制整个 translog 操作流)。2.4.0 的修复清单中有大量该方向的条目佐证其成熟度:
Do not fail replica shard due to primary closure(主分片关闭时不再连带失败副本);Fixed cancellation of segment replication events;Bump segment infos counter before commit during replica promotion(副本晋升主分片时递增 segment infos 计数器);Fix NoSuchFileExceptions with segment replication when computing primary metadata snapshots;Update replicas to commit SegmentInfos instead of relying on SIS files from primary shards(副本自行提交 SegmentInfos,不再依赖主分片推送的 SIS 文件);Fix bug of replica shard's translog not purging on index flush when segment replication is enabled。
这些修复共同解决了副本恢复、主备切换、checkpoint 处理与 translog 清理等环节的一致性问题,是段复制从实验走向生产的关键一步。
7. GeoJSON Point 类型支持
Add support for GeoJson Point type in GeoPoint field让geo_point字段可以接收 GeoJSON 规范的 Point 格式输入({"type": "Point", "coordinates": [lon, lat]})。配套修复还包括Fix a bug on handling an invalid array value for point type field(PR #4900),即对 point 类型字段的非法数组值给出正确错误处理。地理类型实现位于 server/src/main/java/org/opensearch/index/mapper(如 GeoPointFieldMapper 等),模块侧可参考 modules/geo。
8. s390x 架构支持与 no-jdk 发行版
Add support for s390x architecture使 OpenSearch 发行版覆盖 IBM Z(s390x)平台;同时Add missing no-jdk distributions、Build no-jdk distributions as part of release build补齐了各平台不带捆绑 JDK 的发行产物(即no-jdk-*系列,见 distribution/archives 下的no-jdk-linux-tar、no-jdk-windows-zip等目录),供自带 JDK 或使用系统 JDK 的环境使用。
9. 搜索背压(Search Backpressure)资源追踪与在途取消
2.4.0 在搜索稳定性方向引入了一套完整的基于资源消耗的 SearchShardTask 在途取消机制:
Add in-flight cancellation of SearchShardTask based on resource consumption;Add resource usage trackers for in-flight cancellation of SearchShardTask;Add search backpressure stats API。
核心实现位于 SearchBackpressureService.java,它按固定周期(默认 1000ms)巡检集群中的搜索任务,依据任务资源使用情况决定是否取消。任务实体见 SearchShardTask.java,统计输出见 SearchShardTaskStats.java 与 SearchShardTaskCancellationStats.java。
模式开关:search_backpressure.mode支持三档(定义于 SearchBackpressureSettings.java):
| 模式 | 说明 |
|---|---|
disabled | 完全关闭背压机制 |
monitor_only(默认) | 仅监控与统计,不实际取消任务 |
enforced | 按阈值实际取消超限任务 |
核心阈值参数(定义于 SearchShardTaskSettings.java,全部为动态、节点级设置):
| 配置项 | 默认值 | 含义 |
|---|---|---|
search_backpressure.search_shard_task.total_heap_percent_threshold | 0.05 | 所有搜索分片任务堆占用总和占堆的比例阈值(0~1),达到后触发在途取消评估 |
search_backpressure.search_shard_task.cpu_time_millis_threshold | 15000 | 单个任务 CPU 时间阈值(毫秒),超过则考虑取消 |
search_backpressure.search_shard_task.elapsed_time_millis_threshold | 30000 | 单个任务挂钟耗时阈值(毫秒),超过则考虑取消 |
search_backpressure.search_shard_task.heap_percent_threshold | 0.005 | 单个任务堆占用比例阈值 |
search_backpressure.search_shard_task.heap_variance | 2.0 | 堆占用方差阈值:任务堆占用 ≥ 已完成任务堆占用移动平均值 × 该值 时考虑取消 |
search_backpressure.search_shard_task.heap_moving_average_window_size | 100 | 计算堆占用移动平均的窗口大小 |
search_backpressure.search_shard_task.cancellation_ratio | 0.1(沿用旧设置默认) | 相对成功完成任务数的取消比例,即每成功完成一个任务向令牌桶放入的令牌数(0~1) |
search_backpressure.search_shard_task.cancellation_rate | 0.003 | 单位毫秒可取消的任务数(令牌桶每毫秒补充速率) |
search_backpressure.search_shard_task.cancellation_burst | 10.0 | 限流前可突发取消的最大任务数 |
从源码注释可以确认,旧的search_backpressure.cancellation_ratio / cancellation_rate / cancellation_burst已被标记为Deprecated,新设置在search_shard_task命名空间下,旧设置保留用于向后兼容并作为新设置的 fallback。设置校验方面,cancellation_ratio必须满足0 < value <= 1.0,cancellation_rate必须> 0,否则启动即报错。
这套机制的实战价值在于:当集群出现慢查询拖垮节点堆/CPU 时,管理员可以先将search_backpressure.mode设为monitor_only观察 stats API 的统计数据,确认阈值合理后再切换为enforced,从而在"保护集群可用性"与"不误杀正常查询"之间取得平衡。
10. 其他新增
Add groupId value propagation tests for ZIP publication task与Plugin ZIP publication groupId value is configurable:构建侧将插件 ZIP 发布的groupId设为可配置,并补充了传播测试,相关逻辑在 buildSrc 的发布实现中。Github workflow for changelog verification:新增 CI 工作流校验 PR 是否按规范补充 CHANGELOG 条目(对应 CHANGELOG.md 的维护约定)。Copy build.sh over from opensearch-build:将构建脚本build.sh同步进仓库(见 scripts/build.sh)。Add feature to ignore indexes starting with dot during shard limit validation:分片数限制校验时忽略以.开头的系统索引,避免内部索引触发分片上限校验。Update GeoGrid base class access modifier to support extensibility:放宽 GeoGrid 基类访问修饰符以支持第三方扩展。
变更与改进(Changed)
- 远程存储目录抽象:
Use RemoteSegmentStoreDirectory instead of RemoteDirectory,将远程 segment 存储从通用 RemoteDirectory 细化为语义明确的 RemoteSegmentStoreDirectory,为后续 segment 级精细管理铺路。 - 加权轮询调度:
Weighted round-robin scheduling policy for shard coordination traffic为分片协调流量引入加权轮询调度策略,与加权路由 API 形成"数据流 + 协调流"双通道调度。 - 索引级远程仓库设置:
Add index specific setting for remote repository允许按索引指定远程仓库,而非全局统一。 - 副本 SegmentInfos 提交:
Update replicas to commit SegmentInfos instead of relying on SIS files from primary shards,副本分片在恢复完成后自行提交 SegmentInfos,消除对主分片文件的隐式依赖(修复项 #4450 为同一问题的补强)。 - 节点角色加载重构:
Load the deprecated master role in a dedicated method instead of in setAdditionalRoles(),将已废弃的 master 角色加载逻辑独立成方法,便于后续清理。 - 日志配置清理:
Change the version to remove deprecated code of adding node name into log pattern of log4j property file,移除 log4j2 配置中把节点名写进日志 pattern 的废弃代码路径(对应 distribution/src/config/log4j2.properties)。 - Log4j JUL Adapter:
Install and configure Log4j JUL Adapter for Lucene 9.4,为 Lucene 9.4 配置 java.util.logging 桥接,统一日志输出。 - 反射 API 优化:
Use getParameterCount instead of getParameterTypes,避免不必要的类型数组构造。
移除项(Removed)
Remove RepositoryData.MIN_VERSION support for next major release:移除旧版RepositoryData.MIN_VERSION支持,为下一个大版本(3.x)的仓库元数据格式升级腾出空间。这意味着低版本集群创建的旧格式仓库元数据在后续主版本中将不再受支持,升级前需确认快照仓库元数据版本。
修复项(Fixed)
2.4.0 的修复面覆盖 Windows 启动、恢复/复制、映射解析与集群稳定性几个重点方向:
Windows 平台启动脚本
opensearch-service.bat start与opensearch-service.bat manager无法运行(#4289);opensearch.bat与opensearch-service.bat install因缺少 logs 目录失败(#4305);opensearch.bat在安装路径含空格时无法执行(#4362);- 修复 Windows 平台构建失败(#4924)。
恢复与段复制
Do not fail replica shard due to primary closure(#4133);- 取消段复制事件的修复(#4225);
Add check to cancel ongoing replication with old primary on onNewCheckpoint on replica(#4363);- 副本晋升时先递增 segment infos 计数器再提交(#4365);
- 扩展 FileChunkWriter 支持传输客户端取消(#4386);
- 计算主分片元数据快照时消除
NoSuchFileException(#4366); - 修复 getSegmentFiles 处理耗时导致的超时(#4434);
- checkpoint 处理时校验分片路由非 primary(#4716);
- 段复制开启时副本 translog 在 flush 后未清理(#4975)。
索引与映射
ignore_malformed设置现在同样忽略对象类型的 malformed 值(#4494);- 修复 rollover 后 alias filter 丢失(#4499);
- 修复 point 类型字段的非法数组值处理(#4900);
- 自动扩缩副本(auto_expand_replicas)校验修复(#4994);
- 读取 analyzer 映射规则时的错误处理(commit 6d20423)。
集群与快照
- 修复索引删除时的
SnapshotsInProgress错误(#4570); - 修复 arm64 架构 JDK 依赖定位错误(#4613);
- 修复 S3 IRSA 场景下获取快照的
accessDeclaredMembers权限异常(#4469); detailed_error关闭时返回有意义的错误消息,替代 "No OpenSearchException found"(#4708)。
其他
- 恢复
org.opensearch.action.support.master.info包中 ClusterInfoRequest 系列类的使用,供子类继承(#4307); - 日期解析器 day of year 默认值修复(#4627);
- regex query string 搜索设置 analyzer(#4219);
- 比 minimal_english 更优的复数词干器(#4738);
- Gradle
publishPluginZipPublicationToXxx任务警告修复(#4696)。
安全更新(Security)
- CVE-2022-41917(#5141):修复 OpenSearch 自身的相关漏洞;
- CVE-2022-25857(#4341):
org.yaml:snakeyaml反序列化 DoS 漏洞,通过升级 snakeyaml 缓解; - CVE-2022-42003(#4781):Jackson Databind 升级至 2.13.4.2 修复的漏洞,涉及 server/licenses/jackson-dataformat-yaml-3.2.2.jar.sha1 等依赖清单(当前仓库已更新至 jackson 3.x)。
依赖升级(Dependencies)
2.4.0 对底层依赖做了一次集中升级,重点包括:
| 依赖 | 变更 | 影响面 |
|---|---|---|
| Apache Lucene | 升级至9.4.1(#4922,中间经 9.4.0 #4661) | 核心索引与查询引擎,配合 Log4j JUL Adapter 调整 |
| Netty | 升级至4.1.84.Final(#4893) | 网络传输层(libs/netty4、modules/transport-netty4) |
| Jackson / SnakeYAML | jackson 2.13.4 + snakeyaml 1.32(#4556),随后 Databind 升至 2.13.4.2 修复 CVE-2022-42003 | 序列化与 YAML 解析 |
| protobuf-java | repository-gcs / repository-hdfs 升至 3.21.7(#4790),再至 3.21.8(#5005) | 对象存储仓库插件 |
| tika | 2.4.0 → 2.5.0(#4791) | ingest-attachment 文档解析 |
| asm / bytebuddy | 9.3 → 9.4 / 1.12.12 → 1.12.18(#4889) | Painless 脚本与动态字节码 |
| woodstox-core | 6.4.0(#4951) | XML 解析 |
| OpenJDK | 2022 年 10 月补丁版本(#4997) | 运行时基线 |
| spotless / xmlbeans / hadoop-hdfs | 6.9.1→6.10.0 / 5.1.0→5.1.1 / 3.3.3→3.3.4 | 构建与 HDFS 仓库 |
| jetty-http / kotlin-stdlib / snakeyaml | 批量升级(#4982) | 服务端组件 |
| zookeeper | hdfs-fixture 升级(#5007、#5047) | 测试基建 |
此外,Exclude jettison version brought in with hadoop-minicluster(#4787)与 httpcore、mockito、slf4j、httpasyncclient、commons-codec 的批量更新(#4308)也一并合入。当前仓库依赖版本清单可参考 gradle/libs.versions.toml。
总结
OpenSearch 2.4.0 是一个"搜索能力 + 集群治理 + 稳定性"三线并进的版本:
- 搜索侧:PIT 为后续 SQL/PPL 查询、分页一致性打下了协议基础;search 节点角色与加权路由为多可用区流量调度提供了 API 与数据模型;可搜索快照则为冷数据降本探索了新路径。
- 稳定性侧:搜索背压从"监控"到"强制取消"提供了完整的参数体系(mode / 各类阈值 / 令牌桶三件套),段复制故障转移与远程存储体系的多项修复让新复制模型与远程 translog 走向可用。
- 安全侧:Lucene、Netty、Jackson、SnakeYAML 等关键依赖的集中升级,以及 CVE-2022-41917、CVE-2022-25857、CVE-2022-42003 的修复,显著降低了已知漏洞面。
如需深入验证本文涉及的功能细节,推荐从以下源码入口开始阅读:搜索背压参数体系见 SearchShardTaskSettings.java 与 SearchBackpressureSettings.java;PIT 见 PointInTimeBuilder.java 与 CreatePitController.java;加权路由见 WeightedRouting.java 与 WeightedRoutingService.java;节点角色见 DiscoveryNodeRole.java。
【免费下载链接】OpenSearch🔎 Open source distributed and RESTful search engine.项目地址: https://gitcode.com/gh_mirrors/op/OpenSearch
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考