分布式搜索和分析引擎——Elasticsearch(基础篇)

cuixiaogang

Elasticsearch 是一个基于 Lucene 的开源分布式搜索和分析引擎,常用于全文检索、日志分析、实时数据处理等场景,具有分布式、高可用、易扩展等特点

核心特点

  • 分布式架构:可自动将数据分散到多个节点,支持水平扩展,轻松应对大规模数据量和高并发请求。
  • 实时搜索与分析:数据一经索引即可被搜索,能快速处理实时数据,满足实时查询和分析需求。
  • 全文检索能力:支持复杂的文本搜索,包括关键词搜索、短语搜索、模糊搜索等,还能对文本进行分词、高亮显示等处理。
  • 灵活的数据模型:采用 JSON 格式存储数据,支持动态映射,可轻松适应不同结构的数据。
  • 高可用性:通过副本机制确保数据的安全性和可靠性,即使部分节点故障,仍能正常提供服务。
  • 丰富的API:提供了 RESTful API,方便与各种应用程序集成。

基本概念

  • 索引(Index):相当于一个数据库,是具有相同结构的文档的集合(可以理解为mysql中的database)。
  • 文档(Document):是 Elasticsearch 中存储的基本数据单元,以 JSON 格式表示(可以理解为mysql中的row)。
  • 字段(Field):文档中的一个数据项,如姓名、年龄等(可以理解为mysql中的field)。
  • 类型(Type):在旧版本中用于对文档进行分类,新版本中已逐步弃用(可以理解为mysql中的table,7.0后,每个database中只存在一个_doc类型,且不可改变)。
  • 字段映射(mapping):定义索引中字段的类型、存储方式、分词器等元数据的配置。
  • 节点(Node):Elasticsearch 集群中的一个服务器实例,负责存储数据和处理请求。
  • 集群(Cluster):由多个节点组成,共同提供搜索和分析服务。
  • 分片(Shards):数据的物理拆分,用于实现数据的分布式存储与并行处理(可对照mongos中的shards cluster)。
  • 路由(Routing):默认情况下,文档根据 _id 或自定义路由值被分配到特定分片

工作原理简单介绍

  • 索引过程:文档被提交到 Elasticsearch 后,会被分解为多个词项,并建立倒排索引,以便快速搜索。
  • 搜索过程:用户发送搜索请求后,Elasticsearch 会根据倒排索引快速找到匹配的文档,并返回结果。
  • 分布式处理:在分布式环境中,搜索请求会被分发到多个节点进行处理,然后将结果汇总返回给用户。

字段类型

核心类型

  • text: 用于全文本搜索的字符串类型。这些字段会被分析(analyzed)处理,即分词、转换等(后面介绍text结合analyzed配置使用方式)。
  • keyword: 用于结构化内容、精确值查找、过滤或排序的字符串类型。不进行分析处理。
  • long:64位int类型。
  • integer:32位int类型。
  • short:16位int类型。
  • byte:8位int类型。
  • double:双精度的浮点型。
  • float:浮点型。
  • date: 日期类型,支持多种格式。
  • boolean: 布尔类型,表示true或false值。
  • binary: 二进制类型,存储二进制数据,不可检索。

复杂类型

  • object: 用于单个JSON对象,允许你将文档嵌套在另一个文档中。
  • nested: 类似于Object类型,但允许数组中的对象独立查询。

Geo types

  • geo-point: 存储地理位置信息(经纬度)。
  • geo-shape: 支持更复杂的地理形状,如多边形或多线。

Specialized types

  • ip: 用于存储IPv4或IPv6地址。
  • completion: 提供自动补全建议。
  • token count: 计算字符串中的词数量。
  • mapper-murmur3: 使用murmur3哈希函数计算字段的哈希值。
  • percolator: 允许你索引查询而不是文档。
  • join: 在同一索引内实现父/子关系。

常用API

集群管理

集群健康状态查询

1
2
3
4
5
6
7
8
9
10
11
GET /_cluster/health

{
"cluster_name": "my_cluster",
"status": "green", // green-健康 yellow-部分节点异常 red-主节点不可用
"timed_out": false,
"number_of_nodes": 3,
"number_of_data_nodes": 3,
"active_primary_shards": 5,
"active_shards": 10
}

查看索引状态

1
2
3
4
5
6
GET /_cat/indices

green open test_v1 PiYFuqpnQIWZ_C17LXlZZQ 90 1 11738997538 4581090700 10.2tb 5.1tb
green open test_v2 iqnfcBkfTvCIL9V6jUg78w 20 1 0 0 8.1kb 4kb
green open test_v3 cjxRWXLWQyiHinPdyFJ5Cg 10 1 1344373296 38806584 392.1gb 196.1gb

字段含义(以第一行为例)

  1. 健康状态(health): green
    • green:所有主分片和副本分片都可用
    • yellow:所有主分片可用,但至少有一个副本分片不可用
    • red:至少有一个主分片不可用
  2. 索引状态(status): open
    • open:索引可正常使用
    • close:索引已关闭,无法搜索或写入,但占用资源极少
  3. 索引名称(index): test_v1
    • 自定义的索引名称,如 test_v1、test_v2。
  4. UUID: PiYFuqpnQIWZ_C17LXlZZQ
    • 索引的唯一标识符,用于内部管理。
  5. 主分片数量(pri): 90
    • 索引的主分片数量,决定了索引的水平扩展能力。
  6. 副本分片数量(rep): 1
    • 每个主分片的副本数量,提供高可用性和读取性能。
  7. 总文档数(docs.total): 11738997538
    • 主分片和副本分片中的文档总数(通常是 docs.pri 的 rep+1 倍)。
  8. 主分片文档数(docs.pri): 4581090700
    • 所有主分片中的文档总数。
  9. 总磁盘空间(store.size):10.2tb
    • 主分片和副本分片占用的总磁盘空间(通常是 store.size 的 rep+1 倍)。
  10. 主分片磁盘空间(pri.store.size): 5.1tb
    • 所有主分片占用的总磁盘空间。

索引操作

创建索引

1
PUT /my_index

删除索引

1
DELETE /my_index

文档操作

添加/更新文档

1
2
3
4
5
6
7
PUT /my_index/_doc/1
{
"title": "Elasticsearch Guide",
"content": "Learn Elasticsearch",
"tags": ["search", "Elasticsearch"],
"date": "2023-01-01"
}
  • URI中的1是这个文档的_id值,如果该数据已存在,则更新数据,如果不存咋,则添加数据

更新文档

1
2
3
4
5
6
POST /my_index/_update/1
{
"doc": {
"content": "Updated content"
}
}

删除文档

1
DELETE /my_index/_doc/1

查询文档

1
GET /my_index/_doc/1

简单查询

1
GET /my_index/_search?q=title:Elasticsearch
  • 在 my_index 中搜索 title 字段包含 “Elasticsearch” 的文档。

DSL查询

1
2
3
4
5
6
7
8
9
10
11
12
GET /my_index/_search
{
"query": {
"match": {
"title": "Elasticsearch"
}
},
"sort": [
{ "date": { "order": "desc" } }
],
"size": 10
}
  • 使用 DSL(Domain Specific Language)语法进行更复杂的搜索,这里搜索 title 字段包含 “Elasticsearch” 的文档,并按 date 字段降序排列,返回前 10 条结果。

聚合查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
GET /my_index/_search
{
"size": 0,
"aggs": {
"tag_count": {
"terms": {
"field": "tags.keyword",
"size": 10
}
},
"avg_date": {
"date_histogram": {
"field": "date",
"calendar_interval": "month"
}
}
}
}
  • 对 tags 字段进行分组统计(统计每个标签出现的次数),并按 date 字段按月进行直方图统计。

其他操作

批量操作

1
2
3
4
POST /_bulk
{ "index" : { "_index" : "my_index", "_id" : "1" } }
{ "title" : "Elasticsearch Basics" }
{ "delete" : { "_index" : "my_index", "_id" : "2" } }
  • 批量执行多个索引、更新或删除操作,提高效率。

滚动搜索(Scroll API)

1
2
3
4
5
6
7
8
9
10
11
12
13
GET /my_index/_search?scroll=1m
{
"query": {
"match_all": {}
},
"size": 1000
}

GET /_search/scroll
{
"scroll_id": "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAD4WYm9laVYtZndUQlNsdDcwakFMNjU1QQ==",
"scroll": "1m"
}
  • 用于处理大量数据,通过 scroll 参数保持搜索上下文,分批次获取结果。

跨集群搜索(Cross-cluster search)

1
2
3
4
5
6
GET /us_*/_search,eu_*/_search
{
"query": {
"match_all": {}
}
}
  • 同时在多个集群的索引上执行搜索(需配置跨集群连接)。