Elasticsearch 1: 基本原理和概念
Elasticsearch 2: 管理索引和文档
Elasticsearch 3: 数据检索和分析
Elasticsearch 4: 相关性检索和组合查询
Elasticsearch 5: 聚集查询
Elasticsearch 6: 索引别名
Elasticsearch 集群
SpringBoot 整合 Elasticsearch
多个节点可以加入同一个集群。在多节点的集群上,同样的数据可以在多台服务器上传播。这有助于性能,因为 Elasticsearch 有了更多的资源;这同样有助于稳定性,如果每份分片至少有 1 个副本分片,那么任何一个节点都可以宕机, 而 Elasticsearch 依然可以进行服务,并返回所有数据。
对于使用 Elasticsearch 的应用程序,集群中有 1 个还是多个节点都是透明的。 默认情况下,可以连接集群中的任一节点并访问完整的数据集,就好像集群只有单独的一个节点。
尽管集群对于性能和稳定性都有好处,但它也有缺点:必须确定节点之间能够足够快速地通信,并且不会产生脑裂。
一份分片是 Lucene 的索引:一个包含倒排索引的文件目录。倒排索引的结构使得 Elasticsearch 在不扫描所有文档的情况下,就能告诉你哪些文档包含特定的词条 (单词) 。
Elasticsearch 索引被分解为多块分片。一份分片是一个 Lucene 的索引,所以 一个 Elasticsearch 的索引由多个 Lucene 的索引组成。
一个分片是一个 Lucene 索引(一个倒排索引)。它默认存储原始文档的内容,再加上一些额外的信息,如词条字典和词频,这些都能帮助到搜索。
词条字典将每个词条和包含该词条的文档映射起来。搜索的时候,Elastisearch 没有必要为了某个词条扫描所有的文档,而是根据这个字典快速地识别匹配的文档。
词频使得 Elasticsearch 可以快速地获取某篇文档中某个词条出现的次数。这对于计算结果的相关性得分非常重要。例如,如果搜索“denver",包含多个 “denver” 的文档通常更为相关。Elasticsearch 将给它们更高的得分,让它们出现在结果列表的更前面。
ES 中的节点类型:
Master-eligible nodes 与 Master node
每个节点启动后,默认就是一个 Master eligible 节点,可以通过设置 node.master:false 来改变,Master-eligible 节点可以参加选主流程,成为 Master 节点,每个节点都保存了集群的状态,但只有 Master 节点才能修改集群的状态信 息,主节点主要负责集群方面的轻量级的动作,比如:创建或删除索引,跟踪集 群中的节点,决定分片分配到哪一个节点,在集群再平衡的过程中,如何在节点间移动数据等。
Data Node
可以保存数据的节点,叫做 Data Node。负责保存分片数据。在数据扩展上起到了至关重要的作用,每个节点启动后,默认就是一个 Data Node 节点,可以通过设置 node.data:false 来改变。
Ingest Node
可以在文档建立索引之前设置一些 ingest pipeline 的预处理逻辑,来丰富和转换文档。每个节点默认启动就是 Ingest Node,可用通过 node.ingest = false 来禁用。
Coordinating Node
Coordinating Node 负责接收 Client 的请求,将请求分发到合适的节点,最终把 结果汇集到一起,每个节点默认都起到了 Coordinating Node 的职责,当然如果 把 master、Data、Ingest 全部禁用,那这个节点就仅是 Coordinating Node 节点了。
Machine Learning Node
用于机器学习处理的节点
put test1
{
"settings": {
"index.number_of_shards": 3,
"index.codec": "best_compression"
}
}
put test1/_settings
{
"index.number_of_replicas": 2
}
http://192.168.42.111:9200/_cluster/state/master_node,nodes?pretty
单机版安装参考Elasticsearch安装与配置
#将 cluster.name 改为和第一个节点一样
cluster.name: my-elk
#给第二个节点配置独立的名字
node.name: node-2
#network.host 改为本机地址
network.host: 192.168.42.111
#将 discovery.seed_hosts 改为本机地址
discovery.seed_hosts: ["192.168.42.111"]
http://192.168.42.111:9200/_cluster/state/master_node,nodes?pretty
向集群增加一个节点前后,索引发生了些什么。在左端,索引的主分片全部分配到节点 Node1,而副本分片分配没有地方分配。在这种状态下,集群是黄色的,因为所有的主分片有了安家之处,但是副本分片还没有。
一旦第二个节点加入,尚未分配的副本分片就会分配到新的节点 Node2,这使得集群变为了绿色的状态。
可以看到集群中有2个节点后,所有的索引都显示green
集群的第二个节点是如何发现第一个节点、并自动地加入集群的,或者在集群中有更多的节点的情况下,如何知道?
Elasticsearch 7.0 中引入的新集群协调子系统来处理这些事,采用的是单播机制,这种机制需要已知节点的列表来进行连接。
单播发现( unicast discovery )让 Elasticsearch 连接一系列的主机,并试图发现更多关于集群的信息。使用单播时,我们告诉 Elasticsearch 集群中其他节点的 IP 地址以及(可选的)端口或端口范围。
在 elasticsearch.yml 中通过 discovery.seed_hosts 配置种子地址列表,这样每个节点在启动时发现和加入集群的步骤就是:
1、去连接种子地址列表中的主机,如果发现某一个 Node 是 Master Eligible Node,那么该 Master Eligible Node 会共享它知道的 Master Eligible Node,这些共享的 Master Eligible Node 也会作为种子地址的一部分继续去试探;
2、直到找到某一个 seed addresss 对应的是 Master Node 为止;
3、如果第二步没有找到任何满足条件的 Node,ES 会默认每隔 1 秒后去重新尝试寻找,默认为 1 秒
4、重复第三步操作直到找到满足条件为止,也就是直到最终发现集群中的主节点,会发出一个加入请求给主节点
5、获得整个集群的状态信息。
为什么实例需要知道集群状态信息?例如,搜索必须被路由到所有正确的分片,以确保搜索结果是准确的。在索引或删除某些文档时,必须更新每个副本。 每个客户端请求都必须从接收它的节点转发到能够处理它的节点。每个节点都了解集群的概况,这样它们就可以执行搜索、索引和其他协调活动。
discovery.seed_hosts 中的节点地址列表,可以包括集群中部分或者全部集群节点,但是建议无论怎样都应该包含集群中 Master-eligible nodes 节点的部分或者全部。
PUT _cluster/settings
{
"transient": {
"cluster.routing.allocation.exclude._name": "node-1"
}
}
PUT _cluster/settings
{
"transient": {
"cluster.routing.allocation.exclude._ip": "192.168.1.10"
}
}
http://192.168.42.111:9200/_cluster/health?pretty
从这个答复的表明信息,我们可以推断出很多关于集群整体健康状态的信息。“cluster_name” : 集群名称
“status” :正常情况下,Elasticsearch 集群健康状态分为三种:
green 最健康得状态,说明所有的分片包括备份都可用; 这种情况 Elasticsearch 集群所有的主分片和副本分片都已分配, Elasticsearch 集群是 100% 可用的。
yellow 基本的分片可用,但是备份不可用(或者是没有备份); 这种情况 Elasticsearch 集群所有的主分片已经分片了,但至少还有一个副本是缺失的。不会有数据丢失,所以搜索结果依然是完整的。不过,你的高可用性在某种程度上 被弱化。如果更多的分片消失,你就会丢数据了。把 yellow 想象成一个需要及时调查的警告。
red 部分的分片可用,表明分片有一部分损坏。此时执行查询部分数据仍然可以查到,遇到这种情况,还是赶快解决比较好; 这种情况 Elasticsearch 集群至少一个主分片(以及它的全部副本)都在缺失中。这意味着你在缺少数据:搜索只能返回部分数据,而分配到这个分片上的写入请求会返回一个异常。
“timed_out” : 是否有超时
“number_of_nodes” : 集群中的节点数量
“number_of_data_nodes” : 数据节点数
“active_primary_shards” : 指出你集群中的主分片数量
“active_shards” : 所有索引的_所有_分片的汇总值,即包括副本分片
“relocating_shards” : 大于 0 表示 Elasticsearch 正在集群内移动数据的分片,来提升负载均衡和故 障转移。这通常发生在添加新节点、重启失效的节点或者删除节点的时候,因此 出现了这种临时的现象
“initializing_shards” : 当用户刚刚创建一个新的索引或者重启一个节点的时候,这个数值会大于 0
“unassigned_shards” : 这个值大于 0 的最常见原因是有尚未分配的副本分片。在开发环境中,这个 问题很普遍,因为单节点的集群其索引默认有 5 个分片和 1 个副本分片。这种情 况下,由于无多余节点来分配副本分片,因此还有 5 个未分配的副本分片
“active_shards_percent_as_number” : 集群分片的可用性百分比,如果为 0 则表示不可用
集群健康 API 提供了更多的细粒度的操作,允许用户进一步地诊断问题。在这个例子中,可以通过添加 level 参数,深入了解哪些索引受到了分片未配置的影响,比如:http://192.168.42.111:9200/_cluster/health?level=indices&pretty=true
http://192.168.42.111:9200/_cat
来查看所支持的_cat API 接口的完整清单。
allocation-展示分配到每个节点的分片数量。
count-统计整个集群或索引中文档的数量。 如:GET _cat/count/employees?v
health–展示集群的健康状态。
indices-展示现有索引的信息。
master—显示目前被选为主节点的节点。
nodes—显示集群中所有节点的不同信息。
recovery–显示集群中正在进行的分片恢复状态。
shards-展示集群中分片的数量、大小和名字。
plugins—展示已安装插件的信息。
put open-soft-shard
{
"settings": {
"index.number_of_shards": 2
}
}
put /open-soft-shard/_doc/1
{
"name": "Apache Hadoop",
"lang": "Java",
"corp": "Apache",
"stars": 200
}
put /open-soft-shard/_doc/2
{
"name": [
"Apache Activemq",
"Activemq Artemis"
],
"lang": "Java",
"corp": "Apache",
"stars": [
500,
200
]
}
put /open-soft-shard/_doc/3
{
"name": [
"Apache Kafka"
],
"lang": "Java",
"corp": "Apache",
"stars": [
500,
400
]
}
put /open-soft-shard/_doc/object
{
"name": [
"Apache ShardingSphere"
],
"lang": "Java",
"corp": "JingDong",
"stars": 400,
"address": {
"city": "BeiJing",
"country": "亦庄"
}
}
{
"nodes" : {
"hwybgn34TuW2LJrOm_FSog" : {
"name" : "node-2",
"ephemeral_id" : "cllkC8AmQVyrBAyyJSNiaA",
"transport_address" : "192.168.42.111:9301",
"attributes" : {
"ml.machine_memory" : "1019797504",
"ml.max_open_jobs" : "512",
"xpack.installed" : "true",
"ml.max_jvm_size" : "1065025536",
"transform.node" : "true"
},
"roles" : [
"data",
"data_cold",
"data_content",
"data_frozen",
"data_hot",
"data_warm",
"ingest",
"master",
"ml",
"remote_cluster_client",
"transform"
]
},
"6Xx-CoJjSquj9kn716ZjnQ" : {
"name" : "node-1",
"ephemeral_id" : "F7phlqAlR6iXhPSMcSjEkw",
"transport_address" : "192.168.42.111:9300",
"attributes" : {
"ml.machine_memory" : "1019797504",
"xpack.installed" : "true",
"transform.node" : "true",
"ml.max_open_jobs" : "512",
"ml.max_jvm_size" : "1065025536"
},
"roles" : [
"data",
"data_cold",
"data_content",
"data_frozen",
"data_hot",
"data_warm",
"ingest",
"master",
"ml",
"remote_cluster_client",
"transform"
]
}
},
"indices" : {
"open-soft-shard" : { }
},
"shards" : [
[
{
"state" : "STARTED",
"primary" : false,
"node" : "6Xx-CoJjSquj9kn716ZjnQ",
"relocating_node" : null,
"shard" : 0,
"index" : "open-soft-shard",
"allocation_id" : {
"id" : "PFQxVNY4SLGplOqICMXJpQ"
}
},
{
"state" : "STARTED",
"primary" : true,
"node" : "hwybgn34TuW2LJrOm_FSog",
"relocating_node" : null,
"shard" : 0,
"index" : "open-soft-shard",
"allocation_id" : {
"id" : "Ucj_fOFATYqUOBlye3nOUA"
}
}
],
[
{
"state" : "STARTED",
"primary" : true,
"node" : "6Xx-CoJjSquj9kn716ZjnQ",
"relocating_node" : null,
"shard" : 1,
"index" : "open-soft-shard",
"allocation_id" : {
"id" : "9FsKkjcSQOOiWhKI4CDxuA"
}
},
{
"state" : "STARTED",
"primary" : false,
"node" : "hwybgn34TuW2LJrOm_FSog",
"relocating_node" : null,
"shard" : 1,
"index" : "open-soft-shard",
"allocation_id" : {
"id" : "5bznRFT0Sr2beunL_BEbFA"
}
}
]
]
}
GET /open-soft-shard/_search_shards?pretty&routing=1
#! Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.14/security-minimal-setup.html to enable security.
{
"nodes" : {
"hwybgn34TuW2LJrOm_FSog" : {
"name" : "node-2",
"ephemeral_id" : "cllkC8AmQVyrBAyyJSNiaA",
"transport_address" : "192.168.42.111:9301",
"attributes" : {
"ml.machine_memory" : "1019797504",
"ml.max_open_jobs" : "512",
"xpack.installed" : "true",
"ml.max_jvm_size" : "1065025536",
"transform.node" : "true"
},
"roles" : [
"data",
"data_cold",
"data_content",
"data_frozen",
"data_hot",
"data_warm",
"ingest",
"master",
"ml",
"remote_cluster_client",
"transform"
]
},
"6Xx-CoJjSquj9kn716ZjnQ" : {
"name" : "node-1",
"ephemeral_id" : "F7phlqAlR6iXhPSMcSjEkw",
"transport_address" : "192.168.42.111:9300",
"attributes" : {
"ml.machine_memory" : "1019797504",
"xpack.installed" : "true",
"transform.node" : "true",
"ml.max_open_jobs" : "512",
"ml.max_jvm_size" : "1065025536"
},
"roles" : [
"data",
"data_cold",
"data_content",
"data_frozen",
"data_hot",
"data_warm",
"ingest",
"master",
"ml",
"remote_cluster_client",
"transform"
]
}
},
"indices" : {
"open-soft-shard" : { }
},
"shards" : [
[
{
"state" : "STARTED",
"primary" : false,
"node" : "6Xx-CoJjSquj9kn716ZjnQ",
"relocating_node" : null,
"shard" : 0,
"index" : "open-soft-shard",
"allocation_id" : {
"id" : "PFQxVNY4SLGplOqICMXJpQ"
}
},
{
"state" : "STARTED",
"primary" : true,
"node" : "hwybgn34TuW2LJrOm_FSog",
"relocating_node" : null,
"shard" : 0,
"index" : "open-soft-shard",
"allocation_id" : {
"id" : "Ucj_fOFATYqUOBlye3nOUA"
}
}
]
]
}
PUT /employees/_doc/2?routing=rountkey
{
......
}
1、先创建一个名为 study_route 的索引,该索引有 2 个 shard,0 个副本
PUT study_route/
{
"settings": {
"number_of_shards": 2,
"number_of_replicas": 0
}
}
GET _cat/shards/study_route?v
PUT study_route/_doc/a?refresh
{
"data": "A"
}
GET _cat/shards/study_route?v
PUT study_route/_doc/b?refresh
{
"data": "B"
}
GET study_route/_search
8、插入第 3 条数据
PUT study_route/_doc/c?routing=key1&refresh
{
"data": "C"
}
GET _cat/shards/study_route?v
GET study_route/_search
11、插入 docid=a 的数据,并指定 routing=key1
PUT study_route/_doc/a?routing=key1&refresh
{
"data": "A with routing key1"
}
14、插入 docid=b 的数据,使用 key1 作为路由字段的值
GET study_route/_doc/b
GET study_route/_doc/b?routing=key1
PUT <索引名>
{
"settings": {
"number_of_shards": 2,
"number_of_replicas": 0
},
"mappings": {
"_routing": {
"required": true//设置为true,则强制检查;false则不检查,默认为false
}
}
}
PUT study_route1/
{
"settings": {
"number_of_shards": 2,
"number_of_replicas": 0
},
"mappings": {
"_routing": {
"required": true
}
}
}
PUT study_route1/_doc/b?routing=key1
{
"data": "b with routing"
}
GET study_route1/_doc/b
PUT study_route1/_doc/b
{
"data": "B"
}
DELETE study_route1/_doc/b
GET study_route/_search
{
"query": {
"match": {
"data": "B"
}
}
}
GET study_route/_search?routing=key1
{
"query": {
"match": {
"data": "B"
}
}
}