Elasticsearch 第一单元一、ES 基础认知理论ES 是分布式全文检索引擎底层基于 Lucene用 Java 开发主打海量文本检索、日志分析、多维聚合常用于 ELK/ELFK、商品搜索、日志平台。Elasticsearch关系型数据库 MySQL说明Index索引Database 数据库存放一类数据如order_log、goodsType类型Table 表ES7.0 后彻底废弃一个索引只能一种数据Document文档Row 行数据单条数据JSON 格式ES 最小存储单元Field字段Column 列文档内每个键值对如 name、age、contentMapping映射Schema 表结构定义字段类型、分词、索引规则Shard分片分库分表拆分大索引实现水平扩容分主分片 副本分片Query DSLSQLES 专用 JSON 查询语法二、核心概念详解1.集群基础操作实操 1查看集群健康状态GET _cluster/health返回关键字段statusgreen/yellow/rednumber_of_nodes集群节点总数active_shards正常分片数状态解释green主、副本分片全部正常集群健康yellow主分片全部正常副本未分配单机单节点必黄数据不丢red存在主分片丢失索引损坏、数据丢失实操 2查看集群所有节点信息GET _cat/nodes?vv 代表 verbose打印表头可看到节点角色、内存、CPU、磁盘占用实操 3查看集群分片分配详情GET _cat/shards?v2.Index 索引库实操 1创建索引指定主分片、副本数量创建索引goods3 个主分片1 个副本PUT goods { settings: { number_of_shards: 3, number_of_replicas: 1 } }关键规则number_of_shards主分片索引创建后无法修改number_of_replicas副本可随时动态调整实操 2查看单个索引配置GET goods/_settings实操 3修改副本数量动态调整PUT goods/_settings { number_of_replicas: 0 }实操 4查看集群全部索引GET _cat/indices?v实操 5删除索引危险操作DELETE goods3 Document 文档行数据JSON内置系统字段_id文档唯一标识自定义 / 自动生成_index归属索引_source原始完整 JSON 数据_score全文检索匹配分值实操 1新增文档指定自定义_id1PUT goods/_doc/1 { name: 华为Mate60手机, price: 5999, tag: [手机,数码], create_time: 2026-07-19 }实操 2新增文档ES 自动生成_idPOST goods/_doc { name: 小米14, price: 3999, tag: [手机,性价比] }实操 3根据 ID 查询单条文档GET goods/_doc/1实操 4全量修改文档覆盖整条数据PUT goods/_doc/1 { name: 华为Mate60 Pro, price: 6499, tag: [手机,旗舰], create_time: 2026-07-19 }实操 5局部更新文档只改部分字段POST goods/_update/1 { doc: { price: 6299 } }实操 6删除文档DELETE goods/_doc/14 Mapping 映射表结构定义字段类型两大模式动态 mapping写入数据 ES 自动推断字段类型生产不推荐容易类型错乱静态 mapping创建索引时手动定义企业标准用法常用字段类型text可分词用于全文检索商品名称、日志内容keyword不分词精确匹配、聚合、排序标签、手机号long/integer/double数值date日期boolean布尔object普通嵌套对象nested对象数组专用实操 1创建索引同时自定义静态 MappingPUT product { settings: { number_of_shards: 2, number_of_replicas: 1 }, mappings: { properties: { title: { type: text }, brand: { type: keyword }, price: { type: integer }, publish_time: { type: date, format: yyyy-MM-dd } } } }实操 2查看索引 Mapping 结构GET product/_mapping实操 3给已有索引新增字段不能修改原有字段类型PUT product/_mapping { properties: { stock: { type: integer } } }三、底层核心原理理论1 .正向索引数据库存储文档 ID → 完整文本查询方式遍历全部文档逐行匹配海量数据性能极差。2 .倒排索引ES 检索极速的核心结构分词词条 → 文档 ID 列表示例文档doc1华为 Mate60 旗舰手机doc2小米性价比手机分词结果华为、Mate60、旗舰、手机、小米、性价比倒排链表手机[doc1, doc2]华为[doc1]小米[doc2] 查询关键词直接匹配词条不用遍历全量数据毫秒级返回。3 Segment 段、Translog 事务日志Segment磁盘最小存储单元新写入数据生成独立小段后台自动 merge 合并大量小段会消耗 CPU、IO。Translog写入时同步记录事务日志服务器宕机后依靠 translog 恢复未落地磁盘的数据。refresh默认 1s缓冲区数据生成新 segment数据可被检索频繁刷新产生大量小段。flush将 segment 持久化磁盘清空 translog。四、集群节点与分片架构理论1 节点 5 种角色master 主节点管理集群元数据索引、分片分配同一集群仅 1 个活跃 masterdata 数据节点存储分片执行读写、聚合计算业务核心coordinating 协调节点接收客户端请求分发分片任务、合并结果所有节点默认拥有ingest 节点写入前预处理文档清洗数据冷热分层节点hot 热写入、warm 温只读、cold 冷归档2 分片 Shard主分片 primary创建索引指定不可修改文档通过hash(_id) % 主分片数路由到对应分片所有写入先写主分片。副本分片 replica主分片备份不能和主分片同节点提升高可用、分担读压力数量可动态调整。3 故障转移机制节点宕机 → 该节点分片离线 → 副本自动升级为新主分片 → 集群自动创建新副本维持配置副本数量。Elasticsearch 第二单元分词器、DSL 基础查询、文档写入底层流程一、分词器 Analyzer全文检索核心1. 分词器三组件完整执行流程一段文本处理分三步顺序固定Character Filter 字符过滤器清洗原始文本去除 html 标签、替换特殊符号、替换敏感词可配置多个。 例p手机/p→手机Tokenizer 分词器切词核心按规则把文本切割成一个个词条 token。 标准分词、空格分词、IK 中文分词都属于 Tokenizer。Token Filter 词条过滤器对切好的词条二次处理小写转换、停用词删除、同义词扩展、长度过滤。2. ES 内置标准分词器 standard默认特点英文友好中文会单字拆分不适合中文业务。 测试分词 API_analyze调试工具GET _analyze { analyzer: standard, text: 华为Mate60 旗舰智能手机 }输出效果华、为、Mate60、旗、舰、智、能、手、机中文单字拆分无法完整匹配短语3. 中文必备IK 分词器第三方插件两种模式ik_smart粗粒度分词短句合并适合索引存储ik_max_word细粒度全切分拆分所有组合词适合搜索查询IK 分词实操测试GET _analyze { analyzer: ik_max_word, text: 华为Mate60 旗舰智能手机 }输出词条华为、mate60、旗舰、智能、手机、智能手机GET _analyze { analyzer: ik_smart, text: 华为Mate60 旗舰智能手机 }输出词条华为、mate60、旗舰智能手机4. 自定义分词器业务实战创建索引时自定义 analyzer组合字符过滤、分词器、过滤PUT goods { settings: { analysis: { analyzer: { my_ik_analyzer: { tokenizer: ik_max_word, filter: [lowercase] } } } }, mappings: { properties: { title: { type: text, analyzer: my_ik_analyzer }, brand: { type: keyword } } } }5. 字段分词规则区分text字段存入时使用 mapping 指定分词器生成倒排索引查询时同样分词匹配用于模糊搜索keyword字段不分词完整原文作为单个词条只能精确匹配用于筛选、分组、排序。二、Query DSL 基础查询语法前置查询两大分类全文检索match 系列只作用于 text 字段查询关键词会先分词再匹配有相关性_score 分值精确检索term/terms/range作用于 keyword、数值、日期不分词完全匹配无分值适合 filter 过滤2.1 匹配所有文档 match_allGET goods/_search { query: { match_all: {} } }分页控制 size默认 10 条GET goods/_search { query: { match_all: {} }, size: 20 }2.2 全文检索 match最常用text 字段分词模糊匹配GET goods/_search { query: { match: { title: 华为手机 } } }逻辑“华为手机” 分词为华为、手机文档包含任意一个词条都会返回匹配越多分数越高。2.3 短语匹配 match_phrase词条必须连续要求关键词分词后在原文连续出现精准短语搜索GET goods/_search { query: { match_phrase: { title: 华为手机 } } }2.4 多字段检索 multi_match同时在多个 text 字段搜索关键词GET goods/_search { query: { multi_match: { query: 华为, fields: [title,desc] } } }2.5 精确查询 term /termskeyword 专用term单个值精确匹配GET goods/_search { query: { term: { brand: { value: 华为 } } } }terms多值匹配等价 SQL inGET goods/_search { query: { terms: { brand: [华为,小米] } } }重要坑不要用 term 查询 text 字段text 存入是分词后的碎片term 搜完整字符串匹配不到。2.6 区间查询 range价格、时间gte 大于等于lte 小于等于gt 大于lt 小于GET goods/_search { query: { range: { price: { gte: 3000, lte: 7000 } } } }时间区间示例GET goods/_search { query: { range: { create_time: { gte: 2026-01-01, lte: 2026-07-19 } } } }2.7 组合查询 bool业务必用核心bool 包含 4 种子句must必须匹配会计算相关性分值ANDfilter必须匹配不计算分值、自带缓存性能更高过滤条件优先放 filtershould可选匹配满足越多分数越高ORmust_not一定不能匹配无分值示例华为手机价格 3000~8000排除苹果GET goods/_search { query: { bool: { must: [ {match: {title: 手机}} ], filter: [ {term: {brand: 华为}}, {range: {price: {gte:3000,lte:8000}}} ], must_not: [ {term: {brand: 苹果}} ] } } }2.8 排序 sortkeyword、数值、日期字段支持排序text 字段不能直接排序GET goods/_search { query: { match_all: {} }, sort: [ {price: desc}, {create_time: asc} ] }三、文档写入、更新、删除底层完整流程3.1 写入完整流程请求发送至协调节点通过hash(_id) % 主分片数路由到对应主分片节点主分片接收数据写入内存缓冲区内存段同步写入 translog 事务日志持久化磁盘宕机恢复数据主分片同步数据到所有副本分片全部副本写入成功后返回客户端写入成功refresh默认 1 秒缓冲区数据生成独立 Segment 小段写入内存数据变为可检索频繁手动 refresh 会生成大量小段加重合并压力。 手动刷新 APIPOST goods/_refreshflush后台定时执行将内存 Segment 持久化到磁盘清空 translog落地后就算断电数据不丢失。 手动刷盘POST goods/_flushSegment Merge 段合并后台线程自动将多个小 Segment 合并为大 Segment同时清理标记删除的文档合并消耗 CPU/IO是集群常见性能瓶颈。3.2 更新底层原理无原地修改es故意设置ES 底层不支持修改已有 Segment 数据更新逻辑根据_id 查询旧文档给旧文档打上「删除标记」查询时自动过滤标记删除数据写入一条全新完整文档覆盖旧文档不会立刻删除仅段合并时永久清除 大量频繁更新会产生海量小段与删除标记性能大幅下降。3.3 删除底层原理对应文档添加删除标记不会立刻从磁盘清除仅在 Segment 合并阶段彻底移除带删除标记的数据释放磁盘空间3.4 translog 作用缓冲阶段数据仅在内存断电丢失风险translog 实时落盘兜底flush 成功后 translog 清空不需要重复恢复集群重启时读取 translog 恢复未 flush 的数据。Elasticsearch 第三单元聚合 Aggs、分页问题、集群运维、经典三大问题、生产最佳实践一、聚合 Aggs多维统计ES 核心优势聚合分为两大类桶聚合 Bucket分组指标聚合 Metric计算数值1. 指标聚合 Metric单字段统计无分组用于计算最大 / 最小 / 平均 / 总和、去重数量avg平均值sum求和max/min最大最小值count文档总数cardinality基数去重计数类似 distinct实操商品价格统计GET product/_search { size: 0, // 不需要返回原始文档只看聚合结果 aggs: { price_stats: { // 自定义聚合名称 stats: { // 一次性返回avg/sum/max/min/count field: price } }, brand_distinct: { cardinality: { field: brand } } } }2. 桶聚合 Bucket分组类似 group by1terms 普通分组按关键词字段分组统计每个品牌商品数量、均价GET product/_search { size: 0, aggs: { group_by_brand: { terms: { field: brand, size: 10 // 返回前10个分组 }, aggs: { // 分组内嵌套指标聚合 avg_price: { avg: { field: price } } } } } }2date_histogram 时间直方图日志最常用按时间分组按天统计商品上架数量interval 可选hour/day/month/yearGET product/_search { size: 0, aggs: { group_by_day: { date_histogram: { field: online_time, calendar_interval: day, format: yyyy-MM-dd } } } }3range 区间分组按价格区间分组0-3000、3000-6000、6000 以上GET product/_search { size: 0, aggs: { price_range_group: { range: { field: price, ranges: [ {to: 3000}, {from: 3000, to: 6000}, {from: 6000} ] } } } }3. 聚合过滤搭配查询先筛选华为商品再做聚合统计GET product/_search { size: 0, query: { term: { brand: 华为 } }, aggs: { huawei_price_avg: { avg: {field: price} } } }二、分页方案与深度分页性能灾难1. from size前端普通分页有上限缺陷语法示例查询第 100 页每页 10 条GET product/_search { from: 990, size: 10, query: { match_all: {} } }致命问题ES 需要将所有分片前 10000 条数据全部加载到内存排序页数越大内存消耗越高默认index.max_result_window:10000超过直接报错。适用场景只允许前几十页不支持无限下拉翻页2. scroll 游标分页海量数据导出不适合前端翻页原理生成快照保存排序上下文持续滚动拉取全量数据实操初始化 scroll有效期 5 分钟GET product/_search?scroll5m { size: 100, query: {match_all: {}} }返回结果中携带_scroll_id2. 使用 scroll_id 循环拉取下一批GET _search/scroll { scroll: 5m, scroll_id: 返回的scroll_id值 }缺点无法实时获取新增数据占用集群内存不适合前端分页仅用于离线导出数据3. search_after推荐大数据下拉分页无深度限制(类似于游标,惰性求值)基于上一页最后一条文档的排序值向后滚动无 10000 条上限使用前提必须指定唯一稳定排序字段如 _id// 第一页 GET product/_search { size: 10, sort: [ {price: desc}, {_id: asc} // 唯一兜底排序 ] }拿到最后一条文档 sort 数组[5999, 1]// 下一页 GET product/_search { size: 10, search_after: [5999, 1], sort: [ {price: desc}, {_id: asc} ] }优点性能稳定无深度分页限制前端下拉加载首选三、线上三大经典问题缓存穿透、击穿、雪崩ES 常配合 Redis 缓存使用三类问题通用1. 缓存击穿现象某热点数据缓存过期大量并发请求同时直达 ES压垮集群 解决方案热点 key 设置永不过期分布式互斥锁同一时间只放行一个请求查询 ES2. 缓存雪崩现象大量缓存 key 同一时刻过期流量全部打入 ES 解决方案过期时间增加随机偏移值打散过期时间分层设置过期时间避免集中失效3. 缓存穿透现象查询不存在的数据缓存无记录每次都查询 ES如非法 id 解决方案布隆过滤器拦截不存在 id查询空结果时缓存空值设置短过期时间四、集群运维与生产实操命令1. ILM 索引生命周期管理ELK 日志必备自动完成冷热迁移、收缩分片、删除过期日志 四阶段hot热阶段写入查询warm温阶段只读压缩分片cold冷阶段归档降低硬件成本delete删除过期索引2. 快照 snapshot 索引备份恢复创建快照仓库存储备份文件路径对索引打快照全量备份集群故障时从快照恢复索引数据 实操命令创建快照PUT /_snapshot/backup_repo/snapshot_20260719 { indices: product, ignore_unavailable: true, include_global_state: false }3. 冷热数据分层节点节点配置标记node.attr.data_type: hot/warm/cold配合 ILM 自动迁移分片节省服务器成本。4. 分片生产最佳规范单个分片数据控制在 10G ~ 30G主分片数 数据节点数量倍数均衡分片分配生产副本数至少 1单机测试副本 0分片过多大量 segmentmerge 消耗 CPU分片过少单分片数据过大查询慢5. 批量写入 _bulk 高性能 API单请求批量增删改大幅提升写入吞吐量 语法格式操作元数据行 数据行换行分隔POST product/_bulk {index:{_id:4}} {title:OPPO手机,brand:OPPO,price:3499,online_time:2026-04-01} {update:{_id:3}} {doc:{price:2299}} {delete:{_id:2}}规范单批数据控制 500~1000 条单批大小不超过 15MB五、进阶高频知识点面试必考1. BM25 打分算法ES5.0 之后默认替代老旧 TF-IDF 算法解决 TF-IDF 长文档分值虚高问题更贴合真实搜索场景控制词条重复堆砌权重。2. nested 嵌套对象普通 object 数组会扁平化导致关联查询错乱nested 类型将数组对象独立存储支持对象内部精准过滤、聚合。 创建 mapping 示例PUT shop { mappings: { properties: { shop_name: {type:keyword}, goods_list: { type: nested, properties: { goods_name: {type:text}, price: {type:integer} } } } } }查询时必须使用nested查询语法。3. 路由 routing 自定义分片分配文档默认用 _id 哈希分片自定义 routing 字段可将关联数据存入同一分片跨分片聚合性能大幅提升。 写入指定 routingPUT product/_doc/1?routingbrand_huawei { title:华为手机,brand:华为 }查询时必须携带相同 routing否则查不到数据。