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

Elasticsearch的理解与使用

        在大数据与云计算时代,“高效检索” 与 “实时分析” 成为业务突破的关键能力。Elasticsearch(简称 ES)作为一款开源分布式搜索与分析引擎,凭借其低延迟、高可扩、强灵活的特性,已成为日志分析、全文检索、业务监控等场景的 “标配工具”。本文将从 ES 的核心本质出发,深入剖析其架构原理,再通过完整的 Java 代码实现核心功能,帮助开发者从 “认知” 到 “落地” 全面掌握 ES。

一、Elasticsearch 本质认知:它到底是什么?

1. 定位与核心价值

ES 并非传统数据库,而是一款 **“搜索 + 分析” 一体化引擎 **,核心解决 “从海量非结构化 / 半结构化数据中快速找到目标信息” 的问题。与传统数据库(如 MySQL)相比,其优势体现在:

  • 全文检索能力:支持中文、英文等多语言分词,可实现模糊匹配、短语搜索、权重排序(如 “搜索‘苹果手机’时,优先展示销量高的商品”)。
  • 分布式天然适配:数据自动分片存储,集群可轻松扩展至数百节点,承载 PB 级数据。
  • 实时性:数据写入后秒级可检索,延迟通常低于 100ms,满足日志监控、实时推荐等场景。
  • 多维度分析:无需依赖 Hadoop 等工具,通过聚合功能即可实现 “按地区统计订单量”“计算商品价格分布” 等分析需求。

2. 核心概念与传统数据库对比

ES 的术语体系是理解其设计思想的关键,通过与 MySQL 类比可快速掌握:

Elasticsearch 概念

传统数据库(MySQL)

核心作用

Index(索引)

数据库(Database)

存储一类结构相似的数据(如 “商品索引”“用户日志索引”),索引名需小写,无特殊字符

Document(文档)

数据行(Row)

索引的最小数据单元,以 JSON 格式存储(如{"id":"1001","name":"iPhone 15","price":7999})

Field(字段)

数据列(Column)

文档的属性(如 “name”“price”),支持多种类型(text、keyword、integer、date 等)

Mapping(映射)

表结构(Schema)

定义字段的类型、分词器、是否可搜索等规则(如 “将‘name’设为 text 类型,使用 IK 分词器”)

Shard(分片)

无直接对应

将索引拆分后的小分片,分布式存储在不同节点,实现水平扩展(解决单节点存储上限问题)

Replica(副本)

主从复制(Slave)

分片的备份,用于高可用(分片故障时自动切换)和读写分离(副本承担读请求)

注意:ES 7.x 后已废弃Type(类型)(原对应 MySQL 的 Table),原因是 “同一索引下不同 Type 的字段可能冲突,导致分片存储效率低下”,建议通过不同索引区分数据类型(如 “商品索引” 和 “订单索引” 分开创建)。

二、Elasticsearch 架构原理:分布式背后的逻辑

ES 的强大源于其分布式架构设计,理解底层逻辑能帮助开发者在实际项目中避免 “踩坑”(如分片数量不合理导致性能瓶颈)。

1. 集群的核心组成:节点(Node)

一个 ES 集群由多个节点组成,每个节点是一台运行 ES 服务的服务器,按功能可分为 4 类:

  • Master 节点:集群 “管理者”,负责创建索引、分片分配、节点加入 / 退出等管理操作,不承担数据存储和查询压力。建议部署 3 个节点(避免单点故障,通过选举机制实现高可用)。
  • Data 节点:集群 “数据载体”,负责数据的存储(分片)、索引写入和查询请求处理。根据数据量和查询压力横向扩展(如 “从 3 个 Data 节点扩展到 5 个,提升查询吞吐量”)。
  • Coordinating 节点:“请求入口”,接收客户端请求后,将请求分发到相关 Data 节点,汇总结果后返回给客户端。可由 Master 或 Data 节点兼任,高并发场景建议单独部署。
  • Ingest 节点:数据 “预处理管道”,负责数据写入前的清洗(如 “过滤日志中的敏感字段”“将日期格式从‘yyyy-MM-dd’转为‘timestamp’”)。

2. 分片机制:分布式存储的核心

ES 通过分片(Shard) 实现数据的分布式存储,分为 “主分片” 和 “副本分片”:

  • 主分片(Primary Shard):索引创建时指定的分片数量(一旦创建不可修改),用于数据写入和核心查询(如 “创建商品索引时,设置 3 个主分片”)。
  • 副本分片(Replica Shard):主分片的备份,数量可动态调整(如 “为 3 个主分片各创建 1 个副本,共 6 个分片”),与主分片不在同一节点(避免节点宕机导致数据丢失)。

分片分配示例

3 个 Data 节点,创建 “商品索引”(3 个主分片,1 个副本),最终分片分布如下:

  • 节点 1:主分片 P0、副本分片 R1
  • 节点 2:主分片 P1、副本分片 R2
  • 节点 3:主分片 P2、副本分片 R0

此时:

  • 写入数据:客户端请求先到 Coordinating 节点,根据文档 ID 哈希值路由到对应主分片(如 “文档 ID=1001” 路由到 P0),写入成功后同步到副本 R0。
  • 查询数据:Coordinating 节点将请求分发到主分片或副本分片(如 “查询‘iPhone 15’时,同时查询 P0、P1、P2 的副本,并行返回结果”),提升读性能。

3. 数据写入与检索流程

(1)数据写入流程(以 “新增商品文档” 为例)
  • 客户端通过 Java 代码(High Level REST Client)向 Coordinating 节点发送写入请求。
  • Coordinating 节点计算文档 ID 的哈希值,确定应写入的主分片(如 P0)。
  • 主分片 P0 验证文档格式(是否符合 Mapping 规则,如 “price” 是否为数值类型),写入数据并生成倒排索引(全文检索的核心结构,后文详解)。
  • 主分片 P0 将数据同步到副本分片 R0。
  • 副本 R0 同步完成后,主分片 P0 向 Coordinating 节点返回 “写入成功”,最终反馈给客户端。
(2)数据检索流程(以 “搜索‘苹果手机’为例)
  • 客户端发送查询请求到 Coordinating 节点。
  • Coordinating 节点将查询请求分发到所有主分片 / 副本分片(如 P0、P1、P2 及其副本)。
  • 各分片执行查询,返回匹配的文档 ID 和相关性得分(Score,根据 “关键词出现频率”“文档热度” 等计算)。
  • Coordinating 节点汇总所有分片的结果,按得分排序,取前 N 条(如前 20 条),再向对应分片请求完整文档数据。
  • 分片返回完整文档,Coordinating 节点整理结果并返回给客户端。

4. 全文检索核心:倒排索引

ES 之所以能实现高效全文检索,核心在于倒排索引(Inverted Index) 结构,与传统数据库的 “正排索引”(按文档 ID 存储数据)相反:

  • 正排索引:文档 ID → 文档内容(如 “文档 1001 → 我买了一部苹果手机”),适合按 ID 查询,但无法快速匹配 “包含‘手机’的文档”。
  • 倒排索引:关键词 → 包含该关键词的文档 ID 列表(如 “手机 → 文档 1001、文档 1003、文档 1005”),直接通过关键词定位文档,检索效率提升 10 倍以上。

倒排索引的构成

  • 词典(Dictionary):存储所有去重后的关键词(如 “苹果”“手机”“华为”),通常以 B + 树结构存储,便于快速查找。
  • postings 列表(Postings List):记录每个关键词对应的文档 ID、出现位置(如 “‘手机’在文档 1001 的第 3 个字符处出现”)、出现频率(如 “‘手机’在文档 1001 中出现 2 次”),用于计算文档与查询的相关性(Score)。

三、Elasticsearch 核心功能 Java 实战

        ES 官方提供多种客户端(如 Transport Client、High Level REST Client),其中High Level REST Client(7.x + 推荐) 基于 HTTP 协议,支持所有 ES 功能,且与 ES 版本兼容性好。以下实战基于 ES 7.17.0 版本,通过 Java 代码实现全文搜索、聚合分析、数据同步、集群监控等核心功能。

1. 环境准备

(1)Maven 依赖配置

在pom.xml中引入 ES 客户端及相关依赖(版本需与 ES 集群一致):

<dependencies><!-- Elasticsearch High Level REST Client --><dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId><version>7.17.0</version></dependency><!-- Elasticsearch 核心依赖 --><dependency><groupId>org.elasticsearch</groupId><artifactId>elasticsearch</artifactId><version>7.17.0</version></dependency><!-- JSON 解析(用于文档序列化/反序列化) --><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>2.0.32</version></dependency><!-- 日志依赖(用于调试) --><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-simple</artifactId><version>1.7.36</version><scope>test</scope></dependency></dependencies>
(2)ES 客户端初始化(单例模式)

客户端创建成本较高,建议通过单例模式复用,避免频繁创建销毁连接:

import org.apache.http.HttpHost;import org.apache.http.auth.AuthScope;import org.apache.http.auth.UsernamePasswordCredentials;import org.apache.http.client.CredentialsProvider;import org.apache.http.impl.client.BasicCredentialsProvider;import org.elasticsearch.client.RestClient;import org.elasticsearch.client.RestHighLevelClient;import java.io.IOException;/*** ES客户端工具类(单例模式)*/public class EsClientUtils {// 单例客户端实例private static RestHighLevelClient client;// ES集群节点(多个节点用逗号分隔)private static final String ES_NODES = "192.168.1.100:9200,192.168.1.101:9200";// ES账号密码(若未开启认证,可删除相关代码)private static final String USERNAME = "elastic";private static final String PASSWORD = "123456";// 私有构造器(防止外部实例化)private EsClientUtils() {}/*** 获取ES客户端实例*/public static RestHighLevelClient getClient() {if (client == null) {synchronized (EsClientUtils.class) {if (client == null) {// 1. 解析ES节点String[] nodes = ES_NODES.split(",");HttpHost[] httpHosts = new HttpHost[nodes.length];for (int i = 0; i < nodes.length; i++) {String[] hostPort = nodes[i].split(":");httpHosts[i] = new HttpHost(hostPort[0], Integer.parseInt(hostPort[1]), "http");}
// 2. 配置账号密码认证(若未开启认证,可省略)CredentialsProvider credentialsProvider = new BasicCredentialsProvider();credentialsProvider.setCredentials(AuthScope.ANY,new UsernamePasswordCredentials(USERNAME, PASSWORD));// 3. 构建客户端client = new RestHighLevelClient(RestClient.builder(httpHosts).setHttpClientConfigCallback(httpClientBuilder ->httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider)));}}}return client;}/*** 关闭客户端*/public static void closeClient() throws IOException {if (client != null) {client.close();}}}

2. 索引与映射操作(基础必备)

在写入数据前,需先创建索引并定义映射(类似 MySQL 中 “先建表,再插入数据”)。以下代码实现 “创建商品索引(product)”,并定义字段映射规则:

import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;import org.elasticsearch.client.RequestOptions;import org.elasticsearch.client.RestHighLevelClient;import org.elasticsearch.common.settings.Settings;import org.elasticsearch.common.xcontent.XContentBuilder;import org.elasticsearch.common.xcontent.json.JsonXContent;import java.io.IOException;/*** 索引与映射操作示例*/public class EsIndexDemo {// 索引名称private static final String INDEX_NAME = "product";/*** 创建索引并定义映射* 需求:* 1. 主分片数3,副本数1(适合3个Data节点的集群)* 2. 字段映射:* - id:keyword类型(不分词,用于精确匹配)* - name:text类型(分词,使用IK中文分词器)* - brand:keyword类型(不分词,用于分组统计)* - price:double类型(用于范围查询、排序)* - sales:integer类型(用于排序、聚合)* - create_time:date类型(用于时间范围查询)*/public static void createIndexWithMapping() throws IOException {RestHighLevelClient client = EsClientUtils.getClient();// 1. 构建创建索引请求CreateIndexRequest request = new CreateIndexRequest(INDEX_NAME);// 2. 设置索引参数(分片、副本等)request.settings(Settings.builder().put("number_of_shards", 3) // 主分片数.put("number_of_replicas", 1) // 副本数.put("refresh_interval", "1s") // 刷新间隔(数据写入后1秒可检索));// 3. 定义映射规则XContentBuilder mappingBuilder = JsonXContent.contentBuilder();mappingBuilder.startObject().startObject("properties")// id字段:keyword类型(不分词).startObject("id").field("type", "keyword").endObject()// name字段:text类型,使用IK分词器(需提前在ES安装IK插件).startObject("name").field("</doubaocanvas>


文章转载自:

http://rS992sjR.cgthq.cn
http://mLEOi7S5.cgthq.cn
http://dzZc6AMg.cgthq.cn
http://zcsZiT1u.cgthq.cn
http://vWy7NUYl.cgthq.cn
http://4N6HqNBJ.cgthq.cn
http://tJUD3ahe.cgthq.cn
http://jdog1jTh.cgthq.cn
http://v3Yq2aAe.cgthq.cn
http://uoTI8PYK.cgthq.cn
http://HEOPUO5I.cgthq.cn
http://ouwNM0Wg.cgthq.cn
http://yfcsxu4g.cgthq.cn
http://BZkpNZVR.cgthq.cn
http://FLl9QBg3.cgthq.cn
http://itESKYbY.cgthq.cn
http://u7tMWpzA.cgthq.cn
http://jNiouHhq.cgthq.cn
http://IiRNy6K3.cgthq.cn
http://E0gwPdKm.cgthq.cn
http://xvzYB3Vm.cgthq.cn
http://u9BJ4Gyo.cgthq.cn
http://F7pxoDyL.cgthq.cn
http://6MY0szir.cgthq.cn
http://kklvYSlr.cgthq.cn
http://vcySlNcP.cgthq.cn
http://vq9H2J6n.cgthq.cn
http://OHkmw0bW.cgthq.cn
http://tvPpNyAm.cgthq.cn
http://mGQ52eG4.cgthq.cn
http://www.dtcms.com/a/380470.html

相关文章:

  • android ndk编译valgrind
  • 实现调用libchdb.a静态连接库中的未公开导出函数
  • Deepoc具身智能无人机:为天空装上「自主决策大脑」
  • JX2202 直阻变比智能测试系统:重构新能源电力检测效率标准
  • 2025 年PT展前瞻:人工智能+如何走进普通人的生活?
  • 【AI论文】分享即关爱:基于集体强化学习经验共享的高效语言模型(LM)后训练方法
  • 二、网页的“化妆师”:从零学习 CSS
  • Rustdesk server docker-compose 一键搭建教程
  • 江科大《STM32入门教程》
  • ABI解析智能合约
  • 数据分析入门——解读36页指标体系建设方案【附全文阅读】
  • 隐私保护的照片分享:基于 Secure JPEG 的解决方案
  • 【面试笔记-Java开发岗】
  • OpenLayers数据源集成 -- 章节八:天地图集成详解
  • “可信资产IPO +数链金融RWA” 链改2.0六方共识(深圳)
  • linux自定义网卡名字
  • 基于 OpenCV 的眼球识别算法以及青光眼算法识别
  • 灵码产品演示:Maven 示例工程生成
  • TGRS 2025 | DIA 模块:融合全局与局部特征的可变形交互注意力,即插即用,涨点起飞!
  • Uber开发的QueryGPT:自然语言提示生成SQL查询系统演化
  • 流式上机操作步骤
  • python编程原子化多智能体综合编程应用(上)
  • 栈-1047.删除字符串中的所有相邻重复项-力扣(LeetCode)
  • C语言中的内存函数(memcpy, memmove, memcmp, memset)
  • 自动化土壤称重分样系统
  • 太阳光模拟器 | 光辐射测量的基础知识
  • 手搓Tomcat
  • tuxedo11g-可执行文件
  • 全文 - Graphene -- An IR for Optimized Tensor Computations on GPUs
  • 3. 信息系统基础知识