当前位置: 首页 > news >正文

从源码角度了解Elasticsaerch(分布式协调排序、深分页问题)

引文

Elasticsearch基于Lucene所以很多系统实现都在其中,所以可以先看看Lucene的实现:
https://blog.csdn.net/qq_35040959/article/details/147931034

项目组件

不像Kafka这种顶级项目核心性能组件全自己实现,ELK中有很多引用至第三方开放库;

网络模型-Netty

网络模型多重要不必多说,Elasticsearch基于Netty,一个认可度&社区活跃度都非常高的NIO多路复用模型;

存储模型-Lucene

Elasticsearch基于Lucene上提供分布式服务;具体可以看看这篇文章对存储模型的介绍
https://blog.csdn.net/qq_35040959/article/details/147931034

分布式查询

//GET http://localhost:9200/my-index-000001/_search
{"from": 10, //第二页"size": 10, //查询十条"_source": ["title", "priority"], //指定字段返回"query": {"bool": {"must": [{ "match": { "title": "guide" } }//全匹配]}}
}

构建查询
org.elasticsearch.action.search.TransportSearchAction#executeSearch

分发到每个shard
org.elasticsearch.action.search.AbstractSearchAsyncAction#run

发送shard请求
org.elasticsearch.transport.TransportService#sendLocalRequest

单条查询(查询Lucene)
org.elasticsearch.search.query.QueryPhase#searchWithCollector

[Query]阶段查询结果,只包含指定范围的score与docid
org.elasticsearch.action.search.QueryPhaseResultConsumer#consumeResult

聚合数据(对多个shard的数据聚合排序后决定实际获取的)
org.elasticsearch.action.search.FetchSearchPhase#innerRun -> resultConsumer.reduce();

[Fetch]阶段,读取指定docid文档
org.elasticsearch.action.search.FetchSearchPhase#executeFetch

[Query]&[Fetch]步骤基于Lucene的相关性查询与指定docid查询

深分页-search_after分页查询

**<<分布式查询>>**是基于相关性的查询,这种查询会扫描倒排表构建K-TOP堆,这种方法在深页后(如10000页后)查询成本非常高;

search_after必须指定"sort"排序字段后通过"search_after"定位在排序中的其实位置,这种方式没有构建K-TOP的流程,定位到指定的排序偏移量后直接获取,更加快速;
缺点就是不再是相关性排序;

//GET http://localhost:9200/my-index-000001/_search
{"from": 0,   "size": 10,     "_source": ["title", "priority"], "query": {"bool": {"must": [{ "match": { "title": "guide" } }]}},"sort": [{ "_id": "asc" } //强制要求:指定排序(不难理解:没有固定的排序规则,那么给定的search_after将没法用于排查此前已经吐出的数据)],"search_after": [ "QHHnZ5cBTxKf9WaM2zpf"]  //强制要求:上一页最后一条文档_id
}

基于DocValues实现

深分页-scroll查询

search_after不是基于快照,会受到同步数据插入影响,scroll查询对索引打快照;

资源占用与性能对比:

特性Scroll APISearch After API
上下文维护需要维护 _scroll_id 上下文无上下文,仅需传递排序值
内存占用高(需缓存快照和游标状态)低(无持久化状态)
CPU 开销低(顺序扫描,无需动态排序)中等(需动态定位排序值位置)
网络传输批量高效(适合大数据量导出)单页高效(适合高频分页请求)

实时性与一致性对比

特性Scroll APISearch After API
数据一致性强一致性(基于快照,数据静态)弱一致性(实时数据,可能变化)
反映更新否(快照期间索引更新不可见)是(每次查询读取最新数据)
适用场景全量导出、离线分析(如日志备份)实时分页、深度检索(如用户搜索)

todo 快照原理

一致性协议

分布式问题

主节点

Elastic有一下节点角色[Master Node(主节点)]、[Data Node(数据节点)]、[Coordinating Node(协调节点)]三个核心角色(还有其他的角色),主要介绍主节点:

​​主节点(Master Node)​​

  • ​​职责​​:管理集群元数据(索引创建/删除、分片分配、节点状态监控)。

  • 细分类型​​:
    – 候选主节点(Master-Eligible)​​:参与选举,可成为主节点(配置:node.roles: [master])。
    – 仅投票主节点(Voting-Only)​​:仅参与选举投票,不担任主节点(配置:node.roles: [master, voting_only])。

  • ​​最佳实践​​:
    – 生产集群需至少 ​​3个候选主节点​​,且半数以上非仅投票节点,避免脑裂。
    – 与数据节点分离,确保稳定性。

集群中将会只有一个节点成为[Master Node]并为集群中需要强一致性的行为做唯一决策出口

主节点选举

Elasticsearch 的选举机制是对 Raft (论文)的​​工程化改良​​,通过牺牲部分理论严谨性换取分布式搜索场景下的实操效率,核心差异本质是​​性能与强一致性之间的权衡​​

1. 多票制​​

​​节点在同一任期内可多次投票,支持多个候选人同时当选。
​​冲突解决​​:若多个候选人同时当选,ES 采用 ​​“最后当选者有效”​​ 原则(如 Node2 先当选,但收到 Node3 的投票请求后主动退位,最终 Node3 成为主节点)。
​​目的​​:避免小规模集群中因节点同时竞选导致选举失败(如 3 节点均自投),提升选举速度

2. 预投票流程(PreVote)的差异​​

​​Raft :
候选人需确认日志足够新(term 更大或 index 更大)且获得多数支持,才发起正式投票。
​​Elasticsearch 的 PreVote​​:
检查条件更宽松:仅需候选人 term ≥ 当前节点 term,或 term 相同时候选人版本号 ≥ 当前节点版本号。
​​风险​​:宽松条件可能导致网络分区节点频繁发起无效选举,但提高选举速度,同时 ES 通过动态退避机制(back_off_time)降低影响。

3. 状态转换规则的灵活性​​

​​Raft 的严格转换​​:
节点状态需按 Follower → Candidate → Leader 顺序转换,且 Leader 退位后需先回退至 Follower。
​​Elasticsearch 的灵活转换​​:
​​Leader 退位规则​​:Leader 收到任何更高 term 的投票请求(RequestVote)时,​​立即退位为 Candidate​​(而非 Follower)。
​​目的​​:加速新主节点产生,避免旧 Leader 阻塞选举进程

4. 脑裂处理策略​​

​​Raft 的严格多数票​​:
仅获得多数票的分区可选出 Leader,天然避免脑裂。
​​Elasticsearch 的妥协方案​​:
允许多个分区同时选出 Leader,但通过 ​​“最后当选者有效”​​ 和 ​​Leader 主动退位​​ 解决冲突(非实时避免脑裂)。
​​风险​​:极端情况下可能短暂存在多主,但数据一致性通过分片分配机制(主节点唯一管理元数据)保障。

5. 性能与规模适应性​​

​​选举速度​​:
ES 的并行投票和宽松 PreVote 使​​小规模集群选举更快​​(通常 < 500ms)。
Raft 的严格流程在大规模集群中​​稳定性更优​​,ES 需依赖参数调优(如增大 cluster.election.duration)减少竞争。
​​大规模集群挑战​​:
ES 在超 40 节点时可能出现​​频繁主节点切换​​,Raft 可稳定支持 50+ 节点。

在这里插入图片描述

cluster.election.initial_timeout: 100ms   # 初始等待时间
cluster.election.back_off_time: 100ms     # 退避增量
cluster.election.max_timeout: 10s          # 最大等待时间

仅投票节点(Voting-only Node)​​:专用于投票但不存储数据,提升大规模集群选举稳定性。

​​小规模集群​​(<10 节点):ES 默认配置即可,利用多票制提升选举效率。
​​大规模集群​​(>20 节点):
部署专用​​主节点​​(无 data 角色)和​​仅投票节点​​;
调大 cluster.election.duration(如 1s)减少竞争。

添加新分片&重平衡的影响

一、修改副本分片数(Replicas)​​
​​场景​​:增加或减少副本分片数(如从number_of_replicas=1改为2)。
​​特点​​:在线操作,无需重建索引,数据不会丢失。

添加副本可以在线操作:看过raft论文的添加新节点的流程就能理解为什么可以在线操作;

二、修改主分片数(Primary Shards)​​
​​场景​​:调整主分片数量(如从number_of_shards=3改为6)。
​​特点​​:必须重建索引!原始索引数据不会自动迁移到新分片布局。

ES数据使用计算Hash分配数据,修改只能重建索引;

写一致性

相关文章:

  • 【Java】脱离 JVM 约束 GraalVM + Liberica NIK + Spring + Docker 将 Java 编译为平台二进制可执行文件
  • 亚马逊深度整合全食超市,重塑全球跨境电商与生鲜零售格局
  • FPGA基础 -- Verilog语言要素之值集合
  • CentOS7安装MySQL8.0.42
  • 展开说说Android之Retrofit详解_使用篇
  • 深度解析MySQL中的Join算法:原理、实现与优化
  • 如何在 Windows 上打造 macOS 式快速查看体验?
  • 2025最新1000+道Java面试题+答案整理(附JVM/MySQL/Spring/Redis)
  • 136.在 Vue3 中使用 OpenLayers 实现 GroupLayer 的添加、删除、显示、隐藏
  • P2C (Point-to-Curve) 算法深度解析
  • 传统的提示词优化中,损失函数有哪些
  • iOS即时通讯发送图片消息内存暴涨优化
  • 10.C S编程错误分析
  • MySQL 自增主键 ID 设置为 0有坑
  • 二叉树的最大深度题解
  • Apache Kafka Connect任意文件读取漏洞(CVE-2025-27817)
  • AWS Config:概述、优势以及如何开始?
  • Jmeter的三种参数化方式详解
  • 【WPF】WPF 中 `DisplayMemberPath` 与 `SelectedValuePath` 的深入理解与实战应用
  • Kafka Connect架构深度解析:从分布式设计到组件交互机制
  • 做网站运营有前景么/搜索引擎营销的方法包括
  • 网站建设及服务合同/重大新闻事件2023
  • 做网站文字要求/痘痘该如何去除效果好
  • 珠海营销营网站建设公司/网上怎么推广产品
  • 昆明高端网站建设公司/百度高级搜索页面的网址
  • 做外贸的国际网站有哪些/官网seo是什么