深入 Elasticsearch(17):两种搜索引擎的设计选择
上一篇解决了生产运维——分层监控、扩缩容和故障排查。这篇作为系列收尾,回答一个经常被问到的问题:为什么选 Elasticsearch 而不是 Solr(或反过来)。 Elasticsearch 和 Solr 都基于 Apache Lucene。核心搜索能力——倒排索引、BM25 打分、文本分析——本质上相同,因为它们共享同一个底层引擎。差异在于分布式架构、配置哲学、生态绑定和许可协议这些"Lucene 之上"的设计选择。 本文不下"谁更好"的结论,而是给出一个选择框架。 共同基础:Apache Lucene 两者都基于 Lucene 构建。以下能力在两者中本质相同: 倒排索引(FST + Posting List) BM25 打分 Analyzer(Character Filter → Tokenizer → Token Filter) Doc Values(列式存储,用于排序/聚合) BKD-tree(数值和地理范围查询) Segment 不可变 + 后台 merge 理解了 Lucene(本系列第 02 篇),两个搜索引擎的搜索能...
深入 Elasticsearch(16):集群扩缩、监控指标与故障排查
上一篇解决了安全体系——认证、授权、加密的洋葱模型。这一篇进入生产环境中 ES 集群怎样运维。 生产运维的核心工作是监控和排障。ES 提供了丰富的内置 API 来观察集群各层的状态。关键是建立分层监控的思路:从集群健康到节点资源到索引性能到查询诊断,逐层下钻。 本文抓两个问题:生产集群应该监控哪些指标,以及常见故障怎样排查。 分层监控 监控从宏观到微观分四层,每层对应不同粒度的 API 和指标。排查问题时从 L1 开始逐层下钻,定位到具体层再展开: graph TD L1[L1 集群健康<br/>_cluster/health] -->|status != green| L2[L2 节点资源<br/>_nodes/stats] L2 -->|JVM/disk 异常| L3[L3 索引性能<br/>_cat/indices] L3 -->|rejected/慢操作| L4[L4 查询诊断<br/>slow log / profile] L1 -->|green| OK[正常运...
深入 Elasticsearch(15):认证、授权与加密
上一篇解决了性能模型和调优思路——定位瓶颈再针对性调整。这一篇进入 ES 的安全层怎样保护集群。 ES 8.x 默认启用安全功能。在此之前安全是 X-Pack 的商业特性。理解安全层的架构——加密、认证、授权、审计——才能正确配置生产集群的访问控制。 本文只抓一个问题:ES 的安全层从外到内有哪几层,各自保护什么。 四层安全从外到内依次拦截请求,每一层解决一个独立的安全问题: graph LR R[Client Request] --> L1[TLS 加密<br/>防窃听/篡改] L1 --> L2[Authentication<br/>你是谁] L2 --> L3[Authorization<br/>你能做什么] L3 --> L4[Audit Log<br/>你做了什么] L4 --> O[Operation] style L1 fill:#4a90d9,color:#fff style L2 fill:#50b86c,color:#fff...
深入 Elasticsearch(14):搜索延迟、写入吞吐与调优思路
上一篇解决了 segment 和索引的生命周期管理——merge 控制 segment 数量,ILM 管理索引的存储分层。这一篇进入 ES 的性能瓶颈在哪里、调优的思维框架是什么。 性能调优不是背参数表。参数是工具,瓶颈定位才是方法。ES 的性能受搜索延迟和写入吞吐两个维度的独立因素影响,先确定瓶颈在哪个维度的哪个因素上,再针对性调整。 本文只抓一个问题:ES 的性能模型——搜索延迟和写入吞吐分别受什么因素影响,用什么工具定位瓶颈。 搜索延迟的关键因素 1搜索延迟 = f(segment数, query复杂度, shard数, cache命中率, 数据结构选择) 因素 影响机制 观察方式 Segment 数量 每个 segment 独立搜索,结果合并 _segments API Query 复杂度 深层嵌套 bool、wildcard、regexp 代价高 _search?profile=true Shard 数量 scatter-gather 开销随 shard 数线性增长 _cat/shards Filesystem cache Lucene 文件...
深入 Elasticsearch(13):Segment Merge 与 Index Lifecycle Management
上一篇解决了集群协调——master 选举和 cluster state 同步。这一篇进入 segment 随时间增长后怎样管理。 第 02 篇介绍了 segment 是不可变的,写入产生新 segment。随着写入持续,segment 数量会不断增长。segment 太多搜索变慢,删除的文档占据的空间不会自动回收。Segment merge 和 ILM 分别在 Lucene 层和 index 层解决这个存储生命周期问题。 本文抓两个问题:为什么需要 segment merge,以及 ILM 怎样管理索引的生命周期。 Segment Merge 为什么需要 merge 每次 refresh 产生一个新 segment。持续写入的 index 会积累大量小 segment。问题有二: 搜索时需要遍历所有 segment。segment 越多,搜索越慢。 删除文档只是在 .liv 文件中打标记,物理空间不回收。只有 merge 时才真正删除标记文档、回收空间。 123456789101112写入阶段: refresh → seg0(10 docs) refresh → se...
深入 Elasticsearch(12):Master 选举与集群状态同步
上一篇解决了副本机制和故障恢复——primary-replica 的同步模型和 failover 流程。这一篇进入谁来决定 shard 分配、节点角色——集群协调层。 cluster state 是 ES 集群的元数据核心(第 01 篇已经介绍过它的结构)。这一篇聚焦在 cluster state 的写入方——master 节点——是怎样被选举出来的,以及选举机制在 ES 7.x 经历了什么根本性变化。 本文只抓一个问题:ES 的 master 选举算法和脑裂防护机制。 选举机制的演变 ES 7.0 之前使用 Zen Discovery,一种基于 Bully 算法变体的选举机制。这套机制需要手动配置 discovery.zen.minimum_master_nodes,配置不当容易导致脑裂。 ES 7.0 起改用全新的选举机制,基于学术论文中的共识算法思想(接近 Raft 但不是完整 Raft 实现)。新机制自动管理 quorum,不再需要手动配置 minimum_master_nodes。 版本 选举机制 脑裂防护 < 7.0 Zen Discovery ...
深入 Elasticsearch(11):故障恢复与读写模型
上一篇解决了数据怎样分布到 shard 上——路由公式和分片数不可变的约束。这一篇进入 shard 的副本机制和故障恢复。 每个 primary shard 可以有零个或多个 replica shard。Replica 提供两个能力:高可用(primary 故障时 replica 接管)和读扩展(搜索请求可以命中 replica)。理解 primary-replica 的同步模型,才能在一致性和可用性之间做出正确的配置选择。 本文只抓一个问题:primary 和 replica 之间怎样同步数据,primary 故障时怎样恢复。 写入模型 一条文档的写入路径经过 primary shard 再转发到 replica: 12345678910Client → Coordinating Node(路由到 primary shard 所在节点) → Primary Shard: 1. 本地执行写入(buffer + translog) 2. 并行转发给所有 in-sync replica → Replica Shard(s): 3. 本地执行同样的...
深入 Elasticsearch(10):数据分布的核心机制
上一篇解决了聚合分析框架——Bucket、Metric、Pipeline 三层聚合在搜索结果上提供实时分析。这一篇进入数据怎样分布到多个 shard 上。 ES 把一个 index 的数据分成多个 shard,分布到不同的节点上。分片的核心是路由公式——决定一条文档应该落在哪个 shard 上。这个公式看起来简单,但它的分母不可变这一约束影响了 ES 的整个容量规划思路。 本文只抓一个问题:分片路由公式怎样工作,以及分片数不可变的约束从何而来。 路由公式 1shard_num = hash(_routing) % number_of_primary_shards 默认情况下 _routing 等于文档的 _id。这个公式把文档 ID 的哈希值对 primary shard 数取模,得到目标 shard 编号。 5 条文档经过这个公式分配到 3 个 shard 的过程: graph LR D1["doc _id=1"] --> H["hash(_id) % 3"] D2["doc _id=2"] -...
深入 Elasticsearch(09):搜索之上的实时分析
上一篇解决了 Query DSL 的查询体系——全文、精确、模糊、地理查询和 bool 组合。这一篇进入在搜索结果之上怎样做实时统计分析。 搜索返回匹配文档的列表。但很多场景不只需要文档列表,还需要统计信息:按类别分组计数、平均价格、日期趋势。ES 的 Aggregation 框架在搜索结果之上提供实时分析能力,不需要把数据导出到 OLAP 系统。 本文只抓一个问题:Aggregation 的三类聚合怎样工作,以及嵌套组合怎样构建复杂分析。 三类聚合 ES 的聚合分为三类,各有不同职责: 1234搜索结果集 → Bucket Aggregation 把文档分到不同的桶里 → Metric Aggregation 在每个桶内计算度量值 → Pipeline Aggregation 在聚合结果上再计算 Bucket 聚合按某种规则把文档分组——类似 SQL 的 GROUP BY。常见的 bucket 聚合: 聚合 分桶规则 类比 SQL terms 按字段值分组 GROUP BY field date_histogram 按时间间隔分组 ...
深入 Elasticsearch(08):从 match 到 bool 的查询体系
上一篇解决了分数怎么算出来的——BM25 的三个因子决定了文档的相关性排序。这一篇进入 Query DSL 的查询类型体系和组合逻辑。 ES 的查询体系不是一个扁平的 API 列表。全文查询、精确查询、模糊查询、地理查询、复合查询分别对应不同的底层数据结构和匹配逻辑。理解这个分类,才能在具体场景中选对查询类型。 本文抓两个问题:ES 的查询类型怎样分类,以及 bool 查询怎样把不同类型的查询组合起来。 查询体系全景 123456789101112131415161718192021222324252627282930313233ES 查询体系├── 全文查询(走 analyzer,参与打分)│ ├── match 分词后多词项匹配│ ├── match_phrase 分词后要求位置相邻│ ├── multi_match 跨多个字段的 match│ └── match_phrase_prefix 短语前缀(输入补全)│├── 精确查询(不走 analyzer,通常用于 filter context)│ ...
