Elasticsearch 底层技术原理以及性能优化实践

一、简介

1. 概述

Elasticsearch是一个基于Lucene库的开源搜索引擎支持分布式、多租户和全文搜索功能。它使用了RESTful API接口可以简化对Elasticsearch的集成和扩展。

2. 应用场景

Elasticsearch广泛应用于全文搜索、日志存储和分析、安全事件检测、业务指标分析等领域。

二、架构

1. 节点和集群

Elasticsearch是一个分布式系统由多个节点组成。节点可以分为两种类型主节点和数据节点

主节点负责协调整个集群中的操作例如创建或删除索引、添加或删除节点等等。每个集群只能有一个主节点当主节点故障时其他节点将会选举出新的主节点。

数据节点存储数据并参与搜索操作。在集群中可以同时存在多个数据节点每个数据节点都包含了所有数据的一部分副本。

节点之间通过使用基于TCP的传输层通信使用JSON格式进行交互。

2. 索引和分片

Elasticsearch使用索引来组织和存储数据。一个索引可以看作是一个关系型数据库中的一个表而每个文档则相当于一行数据。

为了支撑大规模数据存储Elasticsearch将索引分成多个分片(shard)每个分片都是一个独立的Lucene索引。当一个索引被创建时可以指定分片的数量在索引中的每个文档将会被分配到一个确定的分片中。分片的数量一旦确定就不能再更改。

分片带来了好处使得每个分片只需要存储索引的一小部分数据从而使它们更容易被存储在单个节点之上。此外分片还使得Elasticsearch可以水平扩展可以将不同的分片分配给不同的节点。

下面是Java代码展示如何创建一个索引设置分片数量为5副本数量为1

public void createIndex(RestHighLevelClient client, String indexName) throws IOException {
    CreateIndexRequest request = new CreateIndexRequest(indexName);

    // 设置分片数量为5副本数量为1
    request.settings(Settings.builder()
            .put("index.number_of_shards", 5)
            .put("index.number_of_replicas", 1)
    );

    client.indices().create(request, RequestOptions.DEFAULT);
}

三、查询操作原理

1. 查询DSL语法分类

在Elasticsearch中使用Query DSL查询领域特定语言进行查询操作。查询DSL分为两大类查询查询和聚合查询。

1.1. 查询查询

查询查询用于从索引中获取单个或多个文档。以下是常用的查询类型

  • match 查询查找包含指定项的文档。如下所示
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
SearchResponse searchResponse = null;

MatchQueryBuilder matchQueryBuilder = new MatchQueryBuilder("title", "Elasticsearch");
searchSourceBuilder.query(matchQueryBuilder);

SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("index-name");
searchRequest.source(searchSourceBuilder);

searchResponse = client.search(searchRequest, CommonOptions.DEFAULT);
  • term 查询查找与指定术语完全匹配的文档。如下所示
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
SearchResponse searchResponse = null;

TermQueryBuilder termQueryBuilder = new TermQueryBuilder("title.keyword", "Elasticsearch");
searchSourceBuilder.query(termQueryBuilder);

SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("index-name");
searchRequest.source(searchSourceBuilder);

searchResponse = client.search(searchRequest, CommonOptions.DEFAULT);
  • bool 查询将多个查询组合在一起并通过逻辑运算符来确定与查询的真值。如下所示
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
SearchResponse searchResponse = null;

MatchQueryBuilder matchQueryBuilder1 = new MatchQueryBuilder("title", "Elasticsearch");
MatchQueryBuilder matchQueryBuilder2 = new MatchQueryBuilder("content", "Java");

BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
boolQueryBuilder.must(matchQueryBuilder1);
boolQueryBuilder.must(matchQueryBuilder2);

searchSourceBuilder.query(boolQueryBuilder);

SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("index-name");
searchRequest.source(searchSourceBuilder);

searchResponse = client.search(searchRequest, CommonOptions.DEFAULT);

1.2. 聚合查询

聚合查询用于从索引中获取汇总信息。以下是常见的聚合类型

  • avg 聚合计算指定字段的平均值。如下所示
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
SearchResponse searchResponse = null;

AvgAggregationBuilder aggregationBuilder = AggregationBuilders.avg("average_price").field("price");

searchSourceBuilder.aggregation(aggregationBuilder);
searchSourceBuilder.size(0); // return only aggregations and no hits

SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("index-name");
searchRequest.source(searchSourceBuilder);

searchResponse = client.search(searchRequest, CommonOptions.DEFAULT);
  • max 聚合计算指定字段的最大值。如下所示
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
SearchResponse searchResponse = null;

MaxAggregationBuilder aggregationBuilder = AggregationBuilders.max("max_price").field("price");

searchSourceBuilder.aggregation(aggregationBuilder);
searchSourceBuilder.size(0); // return only aggregations and no hits

SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("index-name");
searchRequest.source(searchSourceBuilder);

searchResponse = client.search(searchRequest, CommonOptions.DEFAULT);

2. Lucene 原理基础

Elasticsearch是基于Lucene库开发的。因此了解Lucene的一些基础原理可以更好地理解Elasticsearch的查询操作。Lucene是一个文档检索库用于快速地搜索大量文档。以下是Lucene的一些关键概念

  • Document文档是Lucene中的最小检索单位。每个文档都由多个字段组成。

  • Field字段表示文档的内容。每个字段都有一个名字和值。

  • Analyzer分析器用于将文本转换为词条这些词条将存储在倒排索引中。

  • Inverted Index倒排索引是一个包含单个词汇条目的文档列表的数据结构。它使得快速查找文档成为可能。

  • TF-IDFTF-IDF词频 - 逆文档频率是一种常见的检索评估方法用于计算文档中单词的重要性。

四、性能优化实践

1. 集群设置与调优

1.1 分片

  • 合理设置分片数量
    • 分片数过多会降低索引和搜索的性能
    • 建议每个节点最少设置两个分片
  • 分片平衡
    • Elasticsearch自动将副本分配到其他节点上
    • 考虑使用Shard Allocation Awareness优化跨机架部署避免机架单点故障带来的影响

1.2 副本

  • 合理设置副本数量
    • 副本数过多会增加集群负载导致查询变慢
    • 建议副本数不超过节点数-1
  • 副本位置
    • 数据中心可用性高副本置于其他服务器或数据中心
    • 数据中心可用性低副本置于相同服务器或数据中心

1.3 内存

  • 设置Xmx和Xms参数限制JVM使用的最大和最小内存
  • 注意JVM内存与操作系统缓存的折衷确保JVM能充分利用一定量的操作系统缓存

2. 索引和查询性能优化

2.1 索引

  • 尽量减少分词器的使用
  • 禁用不必要的字段
  • 确定合适的网络延迟参数选择正确的同步级别
  • 通过Bulk API批量插入数据

2.2 查询

  • 查询时避免全文搜索和模糊匹配
  • 排序时应使用docvalue进行优化
  • 尽量使用过滤器而不是查询器实现准确匹配

3. 内存及磁盘使用技巧

3.1 JVM内存分配

  • 应使用cgroup限制Elasticsearch进程的内存使用
  • 使用SSD硬盘加速索引和查询操作
  • 选择合适的JVM垃圾回收策略以减轻内存压力

4. 正确使用搜索建议和聚合功能

4.1 搜索建议

  • 使用completion suggester代替phrase suggester
  • 建议根据具体场景合理设置suggest条目数量

4.2 聚合

  • 对聚合结果进行分析确定最优聚合方式
  • 避免数据分散在数据时间窗口内按照时间排序

五、扩展与集成

1. 插件开发以及集成

在Elasticsearch中插件可以扩展和定制Elasticsearch的功能包括增加新的API端点、集成外部组件或是创建自己的查询方式等等。要开发和集成插件可以按照以下步骤进行

步骤1编写插件代码

开发插件可以使用Java编写并打包成jar文件也可以使用Elasticsearch提供的Gradle插件进行构建。在插件代码中需要实现Plugin接口并覆盖getSettings()方法以提供插件设置默认情况下插件不需要任何设置。此外还需要实现onModule()方法来注册各种组件包括自定义的QueryBuilder、Aggregator等。例如以下代码展示如何注册一个自定义查询

public class MyQueryPlugin extends Plugin {

    @Override
    public Settings getSettings() {
        return Settings.builder()
                .put("my_setting", "default_value")
                .build();
    }

    @Override
    public List<QuerySpec<?>> getQueries(QuerySpecRegistry querySpecRegistry) {
        return Collections.singletonList(
                new QuerySpec.Builder("myQuery", MyQueryBuilder::new, MyQueryBuilder::fromXContent)
                        .build()
        );
    }
    
    // 其他组件的注册
}

步骤2打包插件

完成插件代码编写后需要将插件打包为.zip格式并放入Elasticsearch的plugins目录下。要注意的是在打包插件时需要在根目录下创建es-plugin.properties文件并设置插件的名字和版本号例如

name=my-plugin
version=1.0.0

步骤3安装插件

将插件打包好并放入plugins目录后需要重启Elasticsearch节点以完成插件安装。如果一切正常可以在Elasticsearch的日志中看到类似于以下的输出信息

[2019-04-06T15:55:21,926][INFO ][o.e.p.PluginsService     ] [node-1] loaded module [my-module]
[2019-04-06T15:55:21,927][INFO ][o.e.p.PluginsService     ] [node-1] loaded plugin [my-plugin]

2. 生态系统

Elasticsearch生态系统提供了大量的基于Elasticsearch的工具和库包括

  • Kibana数据可视化和分析平台
  • Logstash日志流处理工具
  • Beats轻量的数据采集代理
  • Elasticsearch-Hadoop连接Hadoop生态系统和Elasticsearch
  • elasticsearch-mapper-attachments插件支持在Elasticsearch中索引和搜索各种文档格式

这些工具和库可以一起使用构建出更加强大、灵活和高效的数据分析和搜索方案。

六、大数据技术集成

1. Hadoop集成

1.1 Hadoop技术介绍

Hadoop是一个开源的分布式数据处理框架最初是为了处理大规模的结构化和半结构化数据而设计。它包括了HDFSHadoop Distributed File System和MapReduce两个核心组件可以实现大规模数据存储、处理和分析。

Elasticsearch是一个开源的搜索引擎基于Lucene构建支持全文搜索、分面搜索、结构化搜索等功能。它被广泛应用在企业级搜索、日志分析、安全分析等领域。

1.2 Hadoop集成方案

Hadoop与Elasticsearch集成主要有以下两种方式

  1. 使用Elasticsearch的Hadoop插件将Elasticsearch作为Hadoop的输出格式可以方便地把Hadoop的计算结果写入到Elasticsearch中。

  2. 使用Hadoop的Elasticsearch插件将Elasticsearch作为Hadoop的输入格式可以直接从Elasticsearch中读取数据进行计算。

1.3 Hadoop集成的优点

Hadoop与Elasticsearch集成可以带来以下几个优点

  1. 处理大规模数据Hadoop可以有效地处理大规模的数据而Elasticsearch则可以对这些数据进行高效的检索和分析结合起来可以实现大规模数据的存储、处理和分析。

  2. 快速检索由于Elasticsearch的搜索引擎支持全文搜索、分面搜索等功能可以快速地检索出需要的数据。

  3. 灵活性Hadoop可以根据数据的不同进行多种计算操作而Elasticsearch也可以根据不同的需求进行数据的不同处理这两个框架的灵活性相互补充可以满足不同场景的需求。

2. Spark集成

2.1 Spark技术介绍

Spark是一个开源的大数据处理框架可以进行内存计算、离线批处理、流式处理、机器学习等多种计算。它具有高速的内存计算能力、良好的易用性和丰富的生态系统。

Spark与Elasticsearch集成可以带来以下几个优点

  1. 高速的内存计算Spark拥有高速的内存计算能力可以快速地处理大规模数据。而Elasticsearch又可以快速地检索所需的数据两者协同可以更快地完成数据处理任务。

  2. 良好的易用性Spark的API具有良好的易用性操作简单直观。通过Spark对Elasticsearch中的数据进行处理可以方便地进行数据分析和挖掘。

2.2 Spark集成方案

Spark可以通过Elasticsearch Hadoop插件实现与Elasticsearch的集成这个插件可以将Spark作为Hadoop的一个计算引擎可以读取和写入Elasticsearch中的数据。具体步骤如下

  1. 下载并安装Elasticsearch Hadoop插件。

  2. 在Spark应用程序中添加相关依赖。

  3. 在Spark应用程序中使用Spark SQL或DataFrame API连接Elasticsearch并进行数据处理。

2.3 Spark集成的优点

Spark与Elasticsearch集成可以带来以下几个优点

  1. 快速处理大数据Spark可以快速地处理大规模数据而Elasticsearch可以快速地检索所需的数据两者协同可以更快地完成数据处理任务。

  2. 容错性Spark具有良好的容错机制可以确保数据处理任务的稳定运行。而Elasticsearch也有自己的容错机制可以防止数据丢失和数据损坏。

3. Logstash集成

3.1 Logstash技术介绍

Logstash是一个开源的数据收集、处理和转发工具可以将各种数据源如Web服务器、数据库、消息队列等中的数据采集并送到不同的目的地。

Logstash可以通过Elasticsearch输出插件将数据写入Elasticsearch中这样就可以快速地实现数据的检索和分析。

3.2 Logstash集成方案

Logstash可以通过Elasticsearch输出插件实现与Elasticsearch的集成具体步骤如下

  1. 下载并安装Logstash和Elasticsearch。

  2. 在Logstash配置文件中添加Elasticsearch输出插件并指定Elasticsearch的连接信息和数据的索引名称等信息。

  3. 启动Logstash并开始数据采集和处理任务。

3.3 Logstash集成的优点

Logstash与Elasticsearch集成可以带来以下几个优点

  1. 高效的数据处理Logstash可以快速地从各种数据源中采集数据并进行处理而Elasticsearch可以对这些数据进行高效的检索和分析。

  2. 灵活性通过Logstash的数据处理管道可以对不同类型的数据进行灵活的处理和转换而Elasticsearch可以根据不同的需求进行数据的不同处理这两个框架的灵活性相互补充可以满足不同场景的需求。

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

“Elasticsearch 底层技术原理以及性能优化实践” 的相关文章

为什么要使用头文件

1.通过头文件来调用库功能。在很多场合,源代码不便(或不准)向用户公布,只 要向用户提供头文件和二进制的库即可。用户只需要按照头文件中的接口声明来调用库 功能,而不必关心接口怎么实现的。编译器会从库中提取相应的代码。 2.头文件能加强类型安全检查。如果某个接...

jsp导出word

<%@ page contentType="application/vnd.ms-word; charset=utf-8"%> <%@ page pageEncoding="utf-8"%> <% String fileName = "jsp导出wor...

怎么使用PHP修改本地地址 - 编程语言

这篇“怎么使用PHP修改本地地址”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“怎么使用PHP修改本地地址”文章吧。 首先,需...

Codeforces Round #201 (Div. 1) / 346A Alice and Bob (数论&想法题)

A. Alice and Bob http://codeforces.com/problemset/problem/346/A time limit per test memory limit per test input...

如何用Vue实现点击导航高亮效果 - web开发

本篇内容介绍了“如何用Vue实现点击导航高亮效果”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成! 一、项目环境准备在开始前,需要先准备一个使用...

学习Python常用的库有哪些 - 编程语言

本篇内容介绍了“学习Python常用的库有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1、Urllib38.93亿次下载Urllib3 是 Python 的 HT...