ElasticSearch索引

ElasticSearch 有三个重要的概念,索引、映射、文档,本文介绍 ElasticSearch 的索引。不同版本的 ElasticSearch API 可能有所区别,本文基于 7.17 版本。

创建索引

向 ElasticSearch 服务发起 PUT 请求 http://service_address:9200/index_name ,如果尝试创建一个已存在的索引名,会返回错误信息。

查询索引

如果要查询全部索引信息,向 ElasticSearch 服务发起 GET 请求 http://service_address:9200/_cat/indices?v ,会展示所有的索引以及索引状态。

1
2
3
health status index                uuid                   pri rep docs.count docs.deleted store.size pri.store.size
green open .geoip_databases MmaF0j3TQaqYssJHr7w21A 1 0 34 28 34.3mb 34.3mb
yellow open test_log d6nGN_fOQ6eqoLqK-wxERg 1 1 0 0 227b 227b

对于表头的各个参数说明如下:

表头 含义
health 当前服务器健康状态: green(集群完整) yellow(单点正常、集群不完整) red(单点不正常)
status 索引打开、关闭状态
index 索引名
uuid 索引统一编号
pri 主分片数量
rep 副本数量
docs.count 可用文档数量
docs.deleted 文档删除状态(逻辑删除)
store.size 主分片和副分片整体占空间大小
pri.store.size 主分片占空间大小

如果要查询单个索引信息,向 ElasticSearch 服务发起 GET 请求 http://service_address:9200/index_name ,会展示该索引的信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
{
"test_log": { // 索引名
"aliases": {}, // 索引别名
"mappings": { // 映射信息
"properties": {
"id": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
}
},
"settings": {
"index": {
"routing": {
"allocation": {
"include": {
"_tier_preference": "data_content"
}
}
},
"number_of_shards": "1", // 索引主分片数量
"provided_name": "test_log",
"creation_date": "1658650554723",
"number_of_replicas": "1", // 索引副本数量
"uuid": "3mBjLre-RB6_jbIemyLNdw",
"version": {
"created": "7171299"
}
}
}
}
}

删除索引

向 ElasticSearch 服务发起 DELETE 请求 http://service_address:9200/index_name

打开/关闭索引

关闭一个索引是一个重要操作,一旦执行,除非再次打开,否则无法对索引进行大量操作,如搜索、分析和更新设置。关闭索引后,还会存在于集群中,但它们不会消耗磁盘空间以外的资源,如果尝试对该索引进行读写操作将会收到索引已关闭的错误信息。

向 ElasticSearch 服务发起 POST 请求 http://service_address:9200/index_name/_close 即可关闭索引。

向 ElasticSearch 服务发起 POST 请求 http://service_address:9200/index_name/_open 即可打开索引。

索引别名

别名是将一个或多个索引映射到一个逻辑名称上的方式,可以提供简洁、易于理解的名称,并将多个索引组合到一个别名下。(例如存在 log_202206 和 log_202207 两个索引,可以使用别名将这两个索引设置为 logs,在查询时只需要使用别名即可查询所有的数据)。索引别名只会影响别名的存在方式,并不会对原始数据造成任何影响。

  • 创建别名

向 ElasticSearch 服务发起 POST 请求 http://service_address:9200/_aliases

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"actions": [
{
"add": {
"index": "log_202206",
"alias": "logs"
}
},{
"add": {
"index": "log_202207",
"alias": "logs"
}
}
]
}
  • 删除别名

删除别名是一个不可逆操作,在执行删除操作之前需要注意是否会影响已有业务的查询等操作。

向 ElasticSearch 服务发起 POST 请求 http://service_address:9200/_aliases

1
2
3
4
5
6
7
8
9
10
{
"actions": [
{
"remove": {
"index": "log_202206",
"alias": "logs"
}
}
]
}
  • 删除所有索引别名
1
2
3
4
5
6
7
8
9
10
{
"actions": [
{
"remove": {
"index": "_all",
"alias": "*"
}
}
]
}
  • 修改别名

已创建的别名无法直接修改,但可以通过删除再新增的方式修改别名。

向 ElasticSearch 服务发起 POST 请求 http://service_address:9200/_aliases

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"actions": [
{
"remove": {
"index": "log_202206",
"alias": "logs"
}
},{
"add": {
"index": "log_202206",
"alias": "log"
}
}
]
}

索引分片与副本

一个索引可以存储超出单个节点硬件限制的大量数据。比如,一个具有10亿文档数据的索引占据 1TB 的磁盘空间,任意节点都可能没有这样大的磁盘空间。或者单个节点处理搜索请求,响应太慢。为了解决这个问题,Elasticsearch 提供了将索引划分成多份的能力,每一份就称之为分片。数据副本是一种保证数据高可用性的方式,Elasticsearch集群可以跨多个节点自动复制数据,以防止单点故障每个分片都可以设置副本数量,每个副本存在于不同的节点上。

分片和副本的设计为 ElasticSearch 提供了支持分布式和故障转移的特性,但并不意味着分片和副本是可以无限分配的。而且索引的分片完成分配后由于索引的路由机制,导致创建索引后分片数是无法修改的,所以索引的分片数量应该谨慎设置。

索引路由计算及分片控制

向索引中新增文档时,文档会被存储到分片中,如果设置了多个分片则涉及到如何在多个分片中查找文档的问题,ElasticSearch 是根据以下公式来决定存储文档的。

shard = hash(routing) % number_of_primary_shards

其中 routing 是一个可变值,默认是文档的 _id 字段,也可以设置为自定义值。通过 hash 函数生成一个数字,然后这个数字再除以 number_of_primary_shards (主分片的数量)后得到余数。这个分布在 0 到 number_of_primary_shards-1 之间的余数,就是文档所在分片的位置。

所以创建索引的时候就要确定好主分片的数量并且永远不会改变这个数量,如果分片数量变化了,那么所有路由的值都会无效,无法按照路由值到对应分片中查找文档。如果确实需要改变分片数量,那么只能新建索引再同步原索引的数据。

在集群中,发送请求到集群中的任意节点,每个节点都有能力处理任意请求。每个节点都知道集群中的文档位置,所以可以直接将请求转发到需要的节点上。如果将所有的请求发送到某一个节点上,可以将这个节点称为协调节点(coordinating node)。

设置索引分片及副本

在创建索引时可以指定索引的分片与副本数量。向 ElasticSearch 服务发起 PUT 请求 http://service_address:9200/index_name

1
2
3
4
5
6
{
"settings": {
"number_of_shards": 3, // 分片数量
"number_of_replicas": 2 // 副本数量
}
}

索引创建后可以修改副本数量。向 ElasticSearch 服务发起 PUT 请求 http://service_address:9200/index_name/_settings

1
2
3
{
"number_of_replicas": 1
}

索引状态说明

  • green(集群完整)

在这个状态下集群中所有的分片和副本都是可用的

  • yellow(单点正常、集群不完整)

在这个状态下集群中有完整的分片可用,但部分副本不完整可用。这种情况不一定是集群故障,也有可能是副本数量设置不合理。

例如:只有单机的 ElasticSearch 节点,但为分片设置了副本数量不为0,此时没有其他节点存放副本,那么索引状态就会变成yellow。

如果使用 SpringData-ElasticSearch 创建索引,默认会将副本数量设置为1。

可以在注解 org.springframework.data.elasticsearch.annotations.Document 指定副本数量为0(@Document(indexName = "index_name", replicas = 0))

自4.2版本开始,@Document 注解标记了相关参数为弃用,可以使用 org.springframework.data.elasticsearch.annotations.Setting 替代指定分片、副本的数量(@Setting(shards = 3, replicas = 0))

  • red(单点不正常)

在这个状态下集群中可能存在副本+分片故障,导致部分数据不可用的问题,需要排除节点故障的问题。