Elasticsearch:分布式搜索引擎数据库

目录

1、核心概念

2、核心价值

3、主要功能

4、限制

5、应用场景

6、使用代码示例(Java)


1、核心概念

Elasticsearch 是一个开源的分布式搜索和分析引擎,它基于 Apache Lucene 构建,能够快速地存储、搜索和分析海量数据。

概念 描述
集群 (Cluster) 由一个或多个节点组成,共同持有整个数据,提供联合索引和搜索能力。
节点 (Node) 集群中的一个服务器,存储数据并参与索引和搜索。节点的类型可以不同(如主节点、数据节点、协调节点等)。
索引 (Index) 具有相似特性的文档集合,可类比为数据库中的表。例如,可以有一个"用户"索引,一个"产品"索引。索引由一个名称(必须全部小写)标识。
文档 (Document) 索引中的基本数据单元,使用JSON格式表示。每个文档都有一个唯一的 ID。
分片和副本 (Shards & Replicas) 索引可以被分成多个分片以支持分布式存储,副本是分片的拷贝,用于提供高可用性。创建索引时,需要指定分片数量,之后无法修改。可以在创建索引后随时动态地更改副本数量。
映射 (Mapping) 用于定义索引中的文档结构和字段类型。
查询 (Query) 用于在索引中搜索和检索文档的操作。

核心技术:倒排索引

  • 通过内容中的关键词找到其所在的文档 ID。Keyword -> Document IDs

  • 例子:

    文档1:{ "content": "The quick brown fox" }

    文档2:{ "content": "Jumped over the lazy dog" }

    文档3:{ "content": "The quick red fox" }
    倒排索引列表(简化版)
    the -> [1, 2, 3]
    quick -> [1, 3]
    brown -> [1]
    fox -> [1, 3]

    ... ...

    当搜索 "quick fox" 时,ES 会分别查找 "quick" 和 "fox" 的文档ID列表,然后取交集,最终快速定位到文档1和文档3。

2、核心价值

Elasticsearch 的核心价值可以总结为三点:搜索日志处理数据分析

  • 强大的搜索能力

    • 全文搜索: 支持复杂的查询,包括模糊查询、短语匹配、同义词、高亮等。

    • 结构化搜索: 对数字、日期、范围等结构化数据进行查询。

    • 相关性评分: 内置 TF-IDF 和 BM25 等算法,能够根据查询与文档的相关性对结果进行智能排序。

  • 可扩展性和可靠性

    • 分布式: 天生为分布式设计,能够轻松处理 PB 级别的数据。

    • 高可用: 通过分片副本机制,确保在部分节点故障时,服务依然可用。

  • 近实时分析

    • 数据在写入后1秒内即可被搜索和分析,非常适合监控、日志分析等需要快速洞察的场景。

3、主要功能

  • 数据索引与搜索: 核心功能,提供丰富的 RESTful API 进行数据的 CRUD 和复杂的查询(如 match, term, bool, range 等)。

  • 聚合:

    • 类比: SQL 中的 GROUP BY,但功能强大得多。

    • 功能: 提供从数据中提取统计信息的能力,如计算平均值、求和、创建直方图、进行分组等。这是其作为"分析引擎"的关键。

  • 自动完成与搜索建议: 通过 Completion Suggester 和 Search-as-you-type 等字段类型,实现高效的自动补全和搜索纠错("你的意思是?")功能。

  • 地理位置搜索与分析: 原生支持 Geo-point 和 Geo-shape,可以轻松实现"查找我附近1公里的餐厅"或"判断点是否在多边形内"等功能。

  • 数据可视化: 与 Kibana 紧密集成,可以将搜索和聚合的结果以丰富的图表、仪表盘形式展现出来。

  • 机器学习: 集成机器学习功能,可以自动检测时间序列数据中的异常,或进行预测性分析。

  • 监控与指标采集: ELK Stack 中的核心组件,专门用于收集和分析日志、指标数据。

  • 安全特性: 提供身份认证、授权、加密通信等安全功能。

4、限制

  • 非事务性:

    • 问题: 不支持 ACID 事务。无法保证跨多个文档的写入操作的原子性。

    • 场景: 不适合金融交易、库存扣减等需要强一致性的场景。

  • 实时性:

    • 问题: 近实时而非严格实时。对于要求毫秒级数据可见性的场景(如极高频的交易系统)可能不适用。
  • 更新开销大:

    • 问题: 更新一个文档实际上是"删除旧文档,索引新文档"的过程。频繁更新代价很高。
  • 资源消耗:

    • 问题: 对内存和 CPU 消耗较高,尤其是为了提升性能而将索引加载到内存中时。
  • 数据关系处理弱:

    • 问题: 不擅长处理复杂的关联关系(如多表 JOIN)。虽然有 nestedjoin 数据类型,但性能损耗大,使用复杂。它更适合"宽表"和"扁平化"的数据模型。
  • 脑裂问题:

    • 问题: 在分布式集群中,如果网络发生分区,可能导致出现多个"主节点",造成数据不一致。需要通过合理的集群配置来避免。

5、应用场景

  • 网站搜索 / 电商平台搜索

    • 描述: 为网站或应用提供强大的搜索功能,支持关键词搜索、过滤器、排序、相关性排名、搜索建议等。

    • 例子: 维基百科、GitHub、电商网站的商品搜索。

  • 日志管理与分析

    • 描述: ELK Stack 的经典应用。收集来自各种服务器、应用程序、网络的日志,进行集中存储、搜索、分析和可视化。

    • 例子: 运维人员通过 Kibana 仪表板实时监控系统错误、追踪性能瓶颈、进行安全审计。

  • 应用程序性能监控

    • 描述: 收集应用程序的性能指标(如响应时间、错误率、吞吐量),通过聚合和分析来监控应用健康状态。

    • 例子: 使用 Elasticsearch 和 APM 服务来追踪微服务架构中的请求链路。

  • 安全分析

    • 描述: 分析来自防火墙、入侵检测系统、终端安全软件的安全事件日志,以检测潜在威胁和异常行为。
  • 商业智能与数据分析

    • 描述: 借助 Elasticsearch 强大的聚合(Aggregations) 功能,从数据中提取复杂的统计信息,进行用户行为分析或业务指标统计。
  • 全文检索与文档管理系统

    • 描述: 为企业内部文档、知识库、法律文书等提供全文检索能力。
  • 内容推荐

    • **描述:**根据用户的历史行为和偏好,Elasticsearch 可以助力内容推荐系统,例如在音乐或视频平台上推荐相似内容。

6、使用代码示例(Java)

添加依赖:

XML 复制代码
<!-- 新的 Elasticsearch Java API Client (推荐用于8.x及以上版本的ES服务端) -->
<dependency>
    <groupId>co.elastic.clients</groupId>
    <artifactId>elasticsearch-java</artifactId>
    <version>8.11.3</version> 
</dependency>
<!-- 需要同时引入RestClient和Jackson -->
<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-client</artifactId>
    <version>8.11.3</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.15.0</version> 
</dependency>

重要提示 :选择客户端时,必须严格遵循官方发布的版本对照表,确保客户端与服务端版本兼容。例如,不能使用8.x的Java API Client连接6.x的ES实例

初始化客户端:

java 复制代码
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;

public class ElasticsearchClientFactory {
    
    public static ElasticsearchClient createClient() {
        // 创建底层 REST client,配置ES服务器地址和端口
        RestClient restClient = RestClient.builder(
            new HttpHost("localhost", 9200, "http")
        ).build();
        
        // 使用Jackson作为JSON映射器创建Transport层
        RestClientTransport transport = new RestClientTransport(
            restClient,
            new JacksonJsonpMapper()
        );
        
        // 创建并返回类型安全的ElasticsearchClient
        return new ElasticsearchClient(transport);
    }
}

索引操作:创建索引、设置映射(Mapping)

java 复制代码
import co.elastic.clients.elasticsearch.indices.CreateIndexTemplateRequest;
import co.elastic.clients.elasticsearch.indices.IndexTemplate;
import co.elastic.clients.elasticsearch.indices.put_index_template.IndexTemplateMapping;

// 使用经典模板方式创建索引和Mapping
CreateIndexTemplateRequest request = CreateIndexTemplateRequest.of(b -> b
    .name("my-index-template")
    .indexPatterns("my-index-*")
    .template(IndexTemplateMapping.of(m -> m
        .mappings(mapping -> mapping
            .properties("id", prop -> prop.long_(l -> l))
            .properties("name", prop -> prop.text(t -> t.store(true).analyzer("ik_smart"))) // 使用IK分词器
            .properties("age", prop -> prop.integer(i -> i.store(true)))
            .properties("desc", prop -> prop.text(t -> t.store(true).analyzer("ik_max_word"))) // 使用IK分词器
            .properties("registerTime", prop -> prop.date(d -> d.format("yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis")))
        )
    )
);

esClient.indices().createIndexTemplate(request);

文档操作:添加/更新文档

java 复制代码
import co.elastic.clients.elasticsearch.core.IndexRequest;
import co.elastic.clients.elasticsearch.core.IndexResponse;

// 准备一个简单的POJO作为文档数据,或者使用Map
public class User {
    private String id;
    private String name;
    private Integer age;
    private String desc;
    private String registerTime;
    // ... getters and setters
}

User user = new User();
user.setId("1");
user.setName("不焦躁的程序员");
user.setAge(10);
user.setDesc("这是一个测试用户");
user.setRegisterTime("2023-10-25 12:00:00");

IndexRequest<Object> indexRequest = IndexRequest.of(b -> b
    .index("testusers") // 索引名称
    .id(user.getId())   // 文档ID
    .document(user)     // 文档源
);
IndexResponse response = esClient.index(indexRequest);

文档操作:查询文档

java 复制代码
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.search.Hit;

// 构建一个match查询
SearchRequest searchRequest = SearchRequest.of(s -> s
    .index("testusers")
    .query(q -> q
        .match(t -> t
            .field("name")
            .query("程序员")
        )
    )
);

SearchResponse<User> searchResponse = esClient.search(searchRequest, User.class);

// 处理搜索结果
for (Hit<User> hit : searchResponse.hits().hits()) {
    User foundUser = hit.source();
    System.out.println("找到用户: " + foundUser.getName());
}

文档操作:删除文档

java 复制代码
import co.elastic.clients.elasticsearch.core.DeleteRequest;
import co.elastic.clients.elasticsearch.core.DeleteResponse;

DeleteRequest deleteRequest = DeleteRequest.of(b -> b
    .index("testusers")
    .id("1")
);
DeleteResponse deleteResponse = esClient.delete(deleteRequest);
相关推荐
Hello.Reader4 小时前
Spark RDD 编程从驱动程序到共享变量、Shuffle 与持久化
大数据·分布式·spark
哦你看看6 小时前
Elasticsearch+Logstash+Filebeat+Kibana部署[7.17.3版本]
大数据·elasticsearch·搜索引擎
小鹿学程序7 小时前
搭建hadoop集群
大数据·hadoop·分布式
web3.08889997 小时前
淘宝(全量)商品详情 API 的分布式请求调用实践
分布式
Hover_Z_快跑7 小时前
Docker 部署 Elasticsearch 8.12 + Kibana + Nginx 负载均衡
nginx·elasticsearch·docker
lijun_xiao20097 小时前
SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式-学习笔记-1
分布式·spring cloud·rabbitmq
二宝1528 小时前
黑马商城day8-ES01
分布式·微服务·架构
凯子坚持 c8 小时前
从零开始:开发一个仓颉三方库的完整实战
大数据·elasticsearch·搜索引擎
shepherd1268 小时前
破局延时任务(下):Spring Boot + DelayQueue 优雅实现分布式延时队列(实战篇)
java·spring boot·分布式