click here to find me😸
本文通过在docker部署一个单节点集群来梳理一下es(Elasticsearch)的基本用法。
1、在docker中安装并启动es
首先拉下一个es镜像,直接输入命令:
docker pull docker.elastic.co/elasticsearch/elasticsearch:7.16.2
可以看出,拉下的es镜像的版本是7.16.2。
下载完成后,输入以下命令来生成一个es容器,并做好端口映射:
docker run -p 127.0.0.1:9200:9200 -p 127.0.0.1:9300:9300 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:7.16.2
启动成功后,需要保持该shell处于打开状态。通过docker ps
命令可以查看对应的容器是否已经创建成功:
docker ps
应输出类似如下的内容:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5eb95097b63f docker.elastic.co/elasticsearch/elasticsearch:7.16.2 "/bin/tini -- /usr/l…" 2 minutes ago Up 2 minutes 127.0.0.1:9200->9200/tcp, 127.0.0.1:9300->9300/tcp exciting_chatterjee
这说明已经成功启动了一个es容器。es提供了简洁、一致的REST API接口,用于管理集群及索引和搜索数据,因此,也可以通过发送如下请求来验证是否部署成功:
curl -X GET "localhost:9200/?pretty"
正常情况下,应该返回如下内容:
{
"name" : "5eb95097b63f",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "AK1fahmTR4KcL0cy2XR4PA",
"version" : {
"number" : "7.16.2",
"build_flavor" : "default",
"build_type" : "docker",
"build_hash" : "2b937c44140b6559905130a8650c64dbd0879cfb",
"build_date" : "2021-12-18T19:42:46.604893745Z",
"build_snapshot" : false,
"lucene_version" : "8.10.1",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}
2、es中的基本概念
本节参考:https://www.elastic.co/guide/en/elasticsearch/reference/6.0/_basic_concepts.html
搜索的核心目的,就是从许多数据(结构化数据、网页、非结构化文档等等)中找到我们的想法最相关的一个或多个记录。为了实现这个目的,通用的做法是先要对待检索的文档建立索引,然后对用户输入的检索语句(query)进行分析与计算,并将匹配得到的结果按照相关性分数由高到低进行排列并返回。
在这个步骤中,有以下几点会影响搜索的效率与准确性:
- 建立索引的算法
- 为大规模文档建立索引时的存储及检索方式
- 解析query以及计算匹配度得分的算法
围绕上述几点来理解es中的一些基本概念,将有助于更好地使用es。
2.1 文档(Document)
在搜索领域,文档指的是可以被用于建立索引的一个基本的数据单元,而不仅仅指通常意义上的那些文档(如word文档、txt文档)。例如,我们在使用百度时,每一条返回结果指向一个网页,那么这个网页就被称为一个文档。
文档也没有大小的限制。例如,你可以对一篇含有8个章节的word文件视作一个文档建立索引,也可以将它们拆分成8个文档再建立索引——这取决于你的实际需求。
待建立索引的文档需要处理成JSON的格式才能被es处理。
2.2 索引(Index)
索引就是一些具有相似特征的文档的集合。例如,你可以为客户数据的创建一个索引、为产品目录创建另一个索引以及为订单数据再创建一个索引。
在es中,索引是由其名称(必须全部是小写字母)进行标识的,这个名称在执行搜索、更新以及删除等操作时会被用到。
2.3 节点(Node)
如果你对分布式存储于计算有过了解,那么对于节点(以及下面的集群)的概念应该不陌生。在es中,一个节点指的就是集群中的一个成员,负责存储数据、建立索引与执行搜索等功能。
节点也是由名称进行标识的,默认情况下,es会为每个节点分配一个全局唯一标识符(UUID),当然,你也可以对其进行自定义。节点名称在统筹管理es集群时是十分关键的。
2.4 集群(Cluster)
集群就是一个或多个节点的集合,其包含了你全部的数据,并提供了在整个集群中(意味着可以跨节点)建立索引并进行搜索的功能。
集群也有一个用于标识的名称,默认情况下,这个名称是“elasticsearch”。在将节点添加到某个集群时,需要指定这个名称。
一个集群可以只包含一个节点。
2.5 分片(Shards)与分片备份(Replicas)
一个索引中的文档数量理论上是没有限制的,但存储过多的文档可能会导致超过该索引所属节点的硬件限制。例如,一个存放10亿个文档的索引大概占用1TB的磁盘空间,单个节点的磁盘空间可能会无法容纳;或者会因为太慢而无法满足单个节点的搜索请求。
为了解决上述问题,es提供了一种对索引进行切分的机制。例如,一个索引被切分为5份,每一份称为一个分片(Shard)。实际上,在创建索引的时候就可以指定要切分的份数。你可以把每一个分片理解为一个小的索引,这意味着它的功能与索引的功能是完全一致的,更重要的是,它可以被放到集群中的任何一个节点上,这样就避免了单节点占用空间太大的问题。
此外,由于不同的分片往往处于不同的节点上,因此可以实现跨节点的分布式处理,从而提升索引与检索的效率。
在生产环境中,为了降低发生故障而带来的损失,即提升系统的高可用性(High Availability),es通过提供备份索引分片(reolicas: replica shards)的方式来缓解这个问题。
因此,在分片备份时需要注意,不要把备份的分片与原始分片放在同一个节点上(否则就失去了备份的意义)。
总结一下:每一个索引都可以被分为指定数量的分片;每一个索引都可以被备份数次(也可以不备份)。如果指定了备份,那么每一个索引的分片将分为两部分:原始分片和备份分片。在创建索引时,用户可以指定分片的数量以及备份的数量。在索引创建完成后,仍可以随时修改备份的数量,但无法修改分片的数量。
3、基本用法
本节介绍一些es的基本用法。
3.1 集群状态
顾名思义,就是查看一下集群的工作状态是否正常。调用API如下:
curl -X GET "localhost:9200/_cluster/health?pretty"
应返回如下内容:
{
"cluster_name" : "docker-cluster",
"status" : "green",
"timed_out" : false,
"number_of_nodes" : 1,
"number_of_data_nodes" : 1,
"active_primary_shards" : 3,
"active_shards" : 3,
"relocating_shards" : 0,
"initializing_shards" : 0,
"unassigned_shards" : 0,
"delayed_unassigned_shards" : 0,
"number_of_pending_tasks" : 0,
"number_of_in_flight_fetch" : 0,
"task_max_waiting_in_queue_millis" : 0,
"active_shards_percent_as_number" : 100.0
}
由于使用了docker,因此集群的名称是“docker-cluster”,它的状态是“green”,这意味着一切正常。此外,还可以看出,该集群只有一个节点,该节点的分片数为3。
其他结果的含义,参考这里。
3.2 创建索引
想要向节点中添加一个索引,执行以下命令:
curl -X PUT "localhost:9200/my-index-000001?pretty" -H 'Content-Type: application/json' -d'
{
"settings": {
"index": {
"number_of_replicas": 0
}
}
}
'
这之后,就成功创建了一个名为“my-index-000001”的索引。可以通过如下方式查看该索引的基本信息:
curl -X GET "localhost:9200/_cat/indices/my-index-000001?v=true"
应该打印如下内容:
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size
green open my-index-000001 OT6xQv8pSVqFdZQduxxEyA 1 0 0 0 226b 226b
如果你在创建索引时所有的参数保持默认状态(
number_of_replicas
的值将会是1
),这时上面的输出的健康状态就会是“yellow”,这是因为该索引的备份数为1,而在当前集群中只有一个节点,即无法将备份分配到另外的节点上进行存储。
3.3 向索引中添加文档
创建索引后,就可以向其中添加文档了:
curl -X POST "localhost:9200/my-index-000001/doc/?pretty" -H 'Content-Type: application/json' -d'
{
"name": "John Doe"
}
'
控制台会打印以下内容:
{
"_index" : "my-index-000001",
"_type" : "doc",
"_id" : "zW-h9X0Bikz8eaXY-itO",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 1,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 0,
"_primary_term" : 1
}
这样,我们的文档就被成功地索引了。
值得注意的是,我们不必先建索引才能向其中写入文档,如果执行索引命令时,该索引尚未创建,那么es将自动创建索引。
3.4 批量索引文件
如果我们的待索引文档有很多,那么3.3中提供了的方法就显得有些麻烦了。因此,es还提供了一种更便捷的方式。
首先,我们可以下载es给出的测试数据,下载地址:accouts.json。
然后,将文件放在工作目录下,并执行如下命令:
curl -H "Content-Type: application/json" -XPOST 'localhost:9200/bank/account/_bulk?pretty&refresh' --data-binary "@accounts.json"
es会创建新的索引“bank”,并且将文档添加进去。
curl -X GET "localhost:9200/_cat/indices/bank?v=true"
输出:
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size
yellow open bank Qo3tB8wiRpao0k6X-Cw8Hw 1 1 1000 0 374.5kb 374.5kb
3.5 搜索
对文档进行索引之后,下一步的操作就是搜索了,可以通过es提供的搜索api实现:
localhost:9200/bank/_search?q=39225&pretty
上述命令指定了在索引“bank”中进行搜索,query是“39225”。一切顺利的话,你应该看到如下的返回结果:
{
"took": 8,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 1.0,
"hits": [
{
"_index": "bank",
"_type": "account",
"_id": "1",
"_score": 1.0,
"_source": {
"account_number": 1,
"balance": 39225,
"firstname": "Amber",
"lastname": "Duke",
"age": 32,
"gender": "M",
"address": "880 Holmes Lane",
"employer": "Pyrami",
"email": "amberduke@pyrami.com",
"city": "Brogan",
"state": "IL"
}
}
]
}
}
可以看到,命中的结果有1个,实际上是命中了结果文档中的“balance”的值。
4、结语
对于es,我也是一个新手,上述过程只能算一个quick start,旨在帮助新手快速入门。es的实际功能要比上面列出来的更全面,也更复杂,想要在实际业务中发挥es的作用,需要去认真读它的说明文档。
文档内容非常详细,堪称技术说明类文档的典范!