Elasticsearch(简称 ES)是一款开源的分布式搜索引擎,基于 Lucene 构建,专注于实时搜索、数据分析和存储,广泛应用于日志分析、电商搜索、监控告警等场景。以下从核心概念、工作原理、架构特点、使用场景等方面进行详解:
一、核心概念
理解 ES 的核心概念是使用它的基础,这些概念与传统数据库有一定对应关系,但更贴合搜索场景:
ES 概念 | 含义 | 与传统数据库对应 |
---|---|---|
Index(索引) | 相似文档的集合(如 “商品索引”“用户日志索引”),相当于数据库中的 “数据库”。 | Database |
Type(类型,7.x 后废弃) | 索引内的文档分类(如 “商品索引” 下的 “电子产品”“服装”),早期类似 “表”。 | Table |
Document(文档) | 索引中的单条数据,以 JSON 格式存储,相当于 “行”。 | Row |
Field(字段) | 文档中的属性(如商品的 “名称”“价格”),相当于 “列”。 | Column |
Mapping(映射) | 定义文档字段的类型(如文本、数字、日期)及分词器等规则,类似 “表结构”。 | Schema |
Shard(分片) | 索引的分片存储单元,分布式存储的核心,分为主分片(Primary)和副本(Replica)。 | 无直接对应,类似数据分片 |
二、核心特性
分布式与高可用
- 索引自动分片(Shard),数据分散存储在多个节点,支持水平扩展。
- 副本分片(Replica)作为主分片的备份,不仅提高可用性(主分片故障时自动切换),还能分担查询压力。
实时搜索
- 基于 Lucene 的倒排索引(Inverted Index),写入数据后秒级可查(近实时,默认 1 秒刷新一次索引)。
- 支持复杂查询(全文检索、模糊匹配、范围查询、聚合分析等)。
灵活的数据分析
- 内置聚合(Aggregation)功能,可对数据进行统计(如求和、平均值)、分组(如按地区统计销量)、嵌套分析等,替代部分数据库的 GROUP BY 或数据仓库的分析能力。
JSON 文档存储
- 文档以 JSON 格式存储,无需严格固定结构(动态映射),适合半结构化数据(如日志、用户行为)。
RESTful API
- 所有操作通过 HTTP API 实现(如创建索引、查询数据),支持多种客户端(Java、Python、Go 等)。
三、工作原理
写入流程
- 数据写入时,首先路由到对应的主分片(根据文档 ID 哈希计算)。
- 主分片写入成功后,同步到副本分片,全部确认后返回 “成功”。
- 写入的数据先存于内存缓冲区,定期(默认 1 秒)刷新到文件系统缓存,生成可搜索的分段(Segment),最终异步刷盘(持久化)。
搜索流程
- 查询阶段(Query Phase):客户端请求发送到任意节点(协调节点),协调节点将查询分发到所有相关分片(主分片或副本),各分片返回匹配文档的 ID 和评分。
- 取回阶段(Fetch Phase):协调节点汇总结果,按评分排序,再从对应分片拉取完整文档,返回给客户端。
倒排索引
- 传统数据库是 “文档→字段” 的正向映射,ES 的倒排索引是 “关键词→文档列表” 的反向映射,例如:
- 文档 1:“Elasticsearch 是搜索引擎”
- 文档 2:“搜索引擎基于 Lucene”
- 倒排索引中,“搜索引擎” 对应文档 1 和文档 2,查询时直接定位相关文档,效率极高。
- 传统数据库是 “文档→字段” 的正向映射,ES 的倒排索引是 “关键词→文档列表” 的反向映射,例如:
四、架构与集群管理
集群(Cluster)
- 由多个节点(Node)组成,共享同一个集群名称(默认 “elasticsearch”),节点自动发现并加入集群。
节点类型
- 主节点(Master Node):管理集群元数据(如索引创建、分片分配),默认每个节点可作为主节点候选,通过选举机制产生活跃主节点。
- 数据节点(Data Node):存储数据分片,负责索引和搜索操作,建议单独配置以提升性能。
- 协调节点(Coordinating Node):处理客户端请求,分发任务和汇总结果,不存储数据,可通过配置禁用主节点和数据节点功能单独作为协调节点。
- ** ingest 节点 **:预处理数据(如字段转换、过滤),适合数据写入前的清洗。
分片管理
- 主分片数量在索引创建时指定,后续不可修改(默认 5 个),副本分片数量可动态调整(默认 1 个)。
- 分片均匀分布在不同节点,确保负载均衡和容错性。
五、常用操作示例
通过 REST API 演示核心操作:
创建索引
bash
PUT /products # 索引名称 { "settings": { "number_of_shards": 3, # 主分片数量 "number_of_replicas": 1 # 副本分片数量 }, "mappings": { "properties": { "name": { "type": "text" }, # 文本类型(支持全文检索) "price": { "type": "float" }, # 数字类型 "create_time": { "type": "date" } # 日期类型 } } }
写入文档
bash
POST /products/_doc/1 # 文档ID为1 { "name": "Elasticsearch实战", "price": 59.9, "create_time": "2023-01-01" }
查询文档
- 全文检索(搜索名称包含 “Elasticsearch” 的商品):
bash
GET /products/_search { "query": { "match": { "name": "Elasticsearch" } } }
- 聚合分析(按价格区间统计商品数量):
bash
GET /products/_search { "size": 0, # 不返回具体文档 "aggs": { "price_ranges": { "range": { "field": "price", "ranges": [ { "to": 50 }, { "from": 50, "to": 100 }, { "from": 100 } ] } } } }
六、适用场景
- 全文检索:电商商品搜索、文档检索、站内搜索(如论坛、知识库)。
- 日志与监控:收集服务器日志、应用监控数据,通过 ES 实时分析异常(结合 ELK Stack:Elasticsearch+Logstash+Kibana)。
- 数据分析:用户行为分析、实时销量统计、舆情监控(如关键词热度追踪)。
- 地理信息搜索:基于地理位置的查询(如 “附近的餐厅”),ES 支持地理坐标类型和距离计算。
七、优缺点与注意事项
- 优点:分布式易扩展、实时性强、查询灵活、支持复杂聚合。
- 缺点:不适合事务性操作(ACID 支持弱)、海量数据下索引优化复杂、内存消耗较高。
- 注意事项:
- 合理设计分片数量(过多导致资源浪费,过少限制扩展)。
- 针对文本字段选择合适的分词器(如中文需使用 IK 分词器)。
- 定期优化索引(如合并分段、删除过期数据)。