引言
Elasticsearch(简称ES)是一个开源的、高扩展的分布式全文搜索引擎,广泛应用于日志分析、实时监控、全文搜索等场景。作为架构师,掌握ES的学习知识体系和实战应用至关重要。本文将从ES的背景、概念、工具、知识点、部署、实战、Java开发、分布式节点、底层逻辑以及分词分类等方面进行详细梳理和介绍,帮助初学者逐步掌握ES技术。
一、ES背景与概念
1.1 ES背景
Elasticsearch由Shay Banon在2010年创建,它基于Lucene开发,但提供了RESTful API风格的接口,支持分布式和水平扩展。随着ES功能的不断强大,它与数据库的边界也越来越小,除了全文检索外,还支持聚合、排序等功能。
1.2 ES核心概念
- 集群(Cluster):一个或多个节点组成,共同承担数据和负载的压力。每个节点通过相同的
cluster.name
配置加入集群。 - 节点(Node):集群中的一个实例,可以是主节点、数据节点或协调节点。主节点负责管理集群变更,数据节点存储数据和倒排索引,协调节点负责请求转发和汇总。
- 索引(Index):数据的容器,类似于关系型数据库中的数据库。每个索引包含多个文档,具有相似结构的文档存储在同一个索引中。
- 文档(Document):索引中的一条记录,使用JSON格式表示。每个文档包含多个字段,每个字段就是一个数据项。
- 分片(Shard):索引中的数据被切分为多个分片,每个分片是一个Lucene实例,可以分布在不同的节点上。分片分为主分片和副本分片,主分片负责数据的读写,副本分片提供数据冗余和读请求服务。
- 倒排索引(Inverted Index):ES快速搜索的关键,它记录了每个词出现过的文档列表,通过词项快速定位到文档。
二、ES工具与知识点
2.1 ES常用工具
- Kibana:ES的可视化工具,用于数据的搜索、分析和展示。
- Logstash:数据收集工具,可以将各种数据源的数据收集起来,并转换为ES可以处理的格式。
- Beats:轻量级数据采集器,用于向ES发送数据。
- Head插件:ES的集群管理工具,用于查看集群状态、节点信息等。
2.2 ES基础API
- GET请求:获取服务器中的对象,相当于SQL的Select命令。
- POST请求:在服务器上更新对象,相当于SQL的Update命令。
- PUT请求:在服务器上创建对象,相当于SQL的Create命令。
- DELETE请求:删除服务器中的对象,相当于SQL的Delete命令。
- HEAD请求:仅用于获取对象的基础信息。
2.3 ES对象模型与关系型数据库对比
- 索引(Index):相当于数据库,用于定义文档类型的存储。
- 文档类型(Type):在ES 7.x之前,一个索引可以有多个类型,但7.x之后逐步淡化这个概念,默认使用
_doc
类型。 - 文档(Document):相当于关系表的数据行,存储数据的载体。
- 字段(Field):文档的一个Key/Value对,相当于关系型数据库表的字段。
三、ES部署与配置
3.1 ES环境部署
3.1.1 Windows系统部署
- 下载并解压:从官网下载Elasticsearch的Windows版本并解压。
- 修改内存配置:在
config/jvm.options
文件中修改JVM内存配置。 - 安装Java JDK:确保已安装Java JDK,并通过
java --version
命令验证。 - 运行ES:双击运行
bin
目录下的elasticsearch.bat
文件,通过浏览器访问http://localhost:9200
验证是否启动成功。
3.1.2 Docker部署
- 拉取镜像:在Docker镜像仓库中查询并下载Elasticsearch镜像。
- 运行容器:使用
docker run
命令启动Elasticsearch容器,并映射相关端口。 - 检查ES状态:通过
curl http://127.0.0.1:9200/
命令检查ES是否启动成功。
3.2 ES集群配置
- 配置文件:在
elasticsearch.yml
中配置集群名称、节点名称、数据路径、日志路径等。 - 发现机制:配置节点的发现机制,如使用单播或组播。
- 分片与副本:设置索引的主分片数和副本数,以平衡性能和可靠性。
四、ES实战应用
4.1 数据索引与查询
4.1.1 添加索引
可以使用PUT请求手动添加索引,也可以通过配置自动创建索引。
json复制代码 PUT /my_index { "settings": { "number_of_shards": 3, "number_of_replicas": 1 }, "mappings": { "properties": { "field1": { "type": "text" }, "field2": { "type": "keyword" } } } }
4.1.2 添加文档
使用POST请求向索引中添加文档。
json复制代码 POST /my_index/_doc/1 { "field1": "value1", "field2": "value2" }
4.1.3 查询文档
使用GET请求查询索引中的文档。
json复制代码 GET /my_index/_doc/1
4.2 高级查询与聚合
4.2.1 组合查询
使用布尔查询(Bool Query)进行组合查询,如must
、should
、must_not
、filter
等。
json复制代码 GET /my_index/_search { "query": { "bool": { "must": [ { "match": { "field1": "value1" } }, { "range": { "field2": { "gte": 10, "lte": 20 } } } ], "filter": [ { "term": { "status": "active" } } ] } } }
4.2.2 聚合分析
使用聚合(Aggregations)进行数据分析,如计算平均值、最大值、最小值、求和等。
json复制代码 GET /my_index/_search { "size": 0, "aggs": { "avg_field1": { "avg": { "field": "field1" } }, "max_field2": { "max": { "field": "field2" } } } }
五、ES与Java开发
5.1 Java客户端
Elasticsearch提供了官方的Java客户端,用于在Java应用程序中与ES进行交互。常用的客户端有RestHighLevelClient和Elasticsearch Java API Client。
5.1.1 RestHighLevelClient
RestHighLevelClient是Elasticsearch官方推荐的高级REST客户端,它提供了丰富的API来操作ES。
java复制代码 import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestClientBuilder; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.builder.SearchSourceBuilder; RestHighLevelClient client = new RestHighLevelClient( RestClient.builder( new HttpHost("localhost", 9200, "http") ) ); SearchRequest searchRequest = new SearchRequest("my_index"); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); searchSourceBuilder.query(QueryBuilders.matchAllQuery()); searchRequest.source(searchSourceBuilder); SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); // 处理搜索响应
5.1.2 Elasticsearch Java API Client
Elasticsearch Java API Client是一个低级别的客户端,它提供了更灵活的方式来与ES进行交互。
java复制代码 import co.elastic.clients.elasticsearch.ElasticsearchClient; import co.elastic.clients.elasticsearch._types.query_dsl.QueryBuilders; 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; RestClient restClient = RestClient.builder(new HttpHost("localhost", 9200, "http")).build(); ElasticsearchClient client = new ElasticsearchClient( new RestClientTransport( restClient, new JacksonJsonpMapper() ) ); SearchResponse searchResponse = client.search( s -> s.index("my_index") .query(q -> q.matchAll(m -> m)) ); // 处理搜索响应
5.2 集成Spring Boot
在Spring Boot项目中,可以通过添加Elasticsearch的依赖来集成ES。
xml复制代码 <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-high-level-client</artifactId> <version>7.13.2</version> </dependency>
然后在配置文件中配置ES的连接信息。
properties复制代码 elasticsearch.host=localhost elasticsearch.port=9200
创建一个配置类来初始化RestHighLevelClient。
java复制代码 import org.apache.http.HttpHost; import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestHighLevelClient; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class ElasticsearchConfig { @Bean public RestHighLevelClient restHighLevelClient() { return new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http")) ); } }
最后,在Service层使用RestHighLevelClient进行ES操作。
java复制代码 import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.builder.SearchSourceBuilder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class ElasticsearchService { @Autowired private RestHighLevelClient restHighLevelClient; public void search() throws IOException { SearchRequest searchRequest = new SearchRequest("my_index"); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); searchSourceBuilder.query(QueryBuilders.matchAllQuery()); searchRequest.source(searchSourceBuilder); SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT); // 处理搜索响应 } }
六、ES分布式节点与底层逻辑
6.1 分布式节点
Elasticsearch是一个分布式系统,通过多个节点协同工作来处理大量数据。每个节点都可以接收客户端的请求,并将请求转发到相应的节点上进行处理。节点之间通过传输层协议进行通信,确保数据的一致性和可靠性。
6.1.1 节点角色
- 主节点(Master Node):负责管理集群的元数据,如索引的创建和删除、节点的加入和离开等。
- 数据节点(Data Node):负责存储数据和倒排索引,处理数据的读写请求。
- 协调节点(Coordinating Node):负责接收客户端的请求,并将请求转发到相应的数据节点上,最后汇总各个节点的响应结果返回给客户端。
6.1.2 分片与副本
Elasticsearch通过分片(Shard)和副本(Replica)来实现数据的分布和容错。每个索引的数据被切分为多个分片,每个分片可以有一个或多个副本。主分片负责数据的读写操作,副本分片提供数据的冗余和读请求服务。当某个节点出现故障时,副本分片可以自动接管主分片的工作,确保数据的可靠性和可用性。
6.2 底层逻辑
Elasticsearch底层基于Lucene实现索引和搜索功能。Lucene是一个高性能、可扩展的信息检索工具库,它提供了完整的查询引擎和索引引擎。Elasticsearch通过封装Lucene的复杂性,提供了简单易用的RESTful API接口。
6.2.1 倒排索引
倒排索引是Elasticsearch快速搜索的关键。它记录了每个词出现过的文档列表,通过词项可以快速定位到文档。倒排索引被写入磁盘后是不可改变的,这保证了索引的不变性和并发安全性。在搜索时,Elasticsearch会根据查询条件在倒排索引中查找匹配的文档列表,并计算每个文档的相关性得分,最后按照得分排序返回结果。
6.2.2 并发控制
Elasticsearch通过乐观并发控制(Optimistic Concurrency Control)来保证数据的一致性和并发性能。在更新文档时,Elasticsearch会先读取文档的当前版本,然后尝试写入新版本。如果文档在读取和写入之间被其他请求修改过,则更新操作会失败,并返回冲突错误。客户端可以根据错误信息进行重试或其他处理。
七、ES分词分类及优缺点
7.1 分词分类
Elasticsearch支持多种分词器(Analyzer),用于将文本数据切分为词项(Token)。常见的分词器有标准分词器(Standard Analyzer)、简单分词器(Simple Analyzer)、空白分词器(Whitespace Analyzer)等。此外,还可以通过自定义分词器来满足特定的需求。
7.1.1 标准分词器
标准分词器是Elasticsearch默认的分词器,它使用标准过滤器链来处理文本数据。标准分词器会将文本切分为单词,并去除标点符号、小写化等。
json复制代码 PUT /my_index { "settings": { "analysis": { "analyzer": { "my_analyzer": { "type": "standard" } } } } }
7.1.2 简单分词器
简单分词器会将文本切分为非空白字符序列,不进行小写化、去除标点符号等处理。
json复制代码 PUT /my_index { "settings": { "analysis": { "analyzer": { "my_analyzer": { "type": "simple" } } } } }
7.1.3 空白分词器
空白分词器会将文本切分为空白字符分隔的序列,不进行其他处理。
json复制代码 PUT /my_index { "settings": { "analysis": { "analyzer": { "my_analyzer": { "type": "whitespace" } } } } }
7.2 分词优缺点
7.2.1 标准分词器
优点:
- 处理能力强,能够处理常见的文本数据。
- 支持多种语言分词。
缺点:
- 对于某些特定领域的文本数据,可能分词效果不佳。
- 需要自定义分词器来满足特定需求。
7.2.2 简单分词器
优点:
- 分词速度快,适用于对分词要求不高的场景。
缺点:
- 分词效果简单,可能无法满足复杂需求。
- 不进行小写化、去除标点符号等处理,可能影响搜索结果。
7.2.3 空白分词器
优点:
- 分词规则简单明了,易于理解。
缺点:
- 分词效果不佳,可能产生大量无意义的词项。
- 不适用于需要精细分词的场景。
八、总结
Elasticsearch作为一个开源的、高扩展的分布式全文搜索引擎,在日志分析、实时监控、全文搜索等场景中具有广泛的应用。作为架构师,掌握ES的学习知识体系和实战应用至关重要。本文从ES的背景、概念、工具、知识点、部署、实战、Java开发、分布式节点、底层逻辑以及分词分类等方面进行了详细梳理和介绍,希望能帮助初学者逐步掌握ES技术,并在实际工作中灵活应用。