使用docker运行集群
参考
Install Elasticsearch with Docker | Elasticsearch Guide [8.12] | Elastic
准备
docker network create elastic
docker pull docker.elastic.co/elasticsearch/elasticsearch:8.12.1
运行第一个节点
docker run --name es01 --net elastic -p 9200:9200 -it -m 1GB docker.elastic.co/elasticsearch/elasticsearch:8.12.1
上述命令会启动一个单节点的elasticseach集群, 关键配置:
cluster.name: "docker-cluster"
network.host: 0.0.0.0
cluster.initial_master_nodes: ["804027f16295"]
cluster.name指定集群名为docker-cluster
cluster.initial_master_nodes指定集群启动的初始节点
启动完成会在控制台输出elastic用户的密码, 可以使用如下命令重置密码
docker exec -it es01 /usr/share/elasticsearch/bin/elasticsearch-reset-password -u elastic
请求elasticsearch的restful借口
ELASTIC_PASSWORD="xxxx"
curl -k -u elastic:$ELASTIC_PASSWORD https://localhost:9200/
返回如下结果, 说明节点正常运行
{
"name" : "804027f16295",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "5gCaQhRNSy2fPI0A0OFV3Q",
"version" : {
"number" : "8.12.1",
"build_flavor" : "default",
"build_type" : "docker",
"build_hash" : "6185ba65d27469afabc9bc951cded6c17c21e3f3",
"build_date" : "2024-02-01T13:07:13.727175297Z",
"build_snapshot" : false,
"lucene_version" : "9.9.2",
"minimum_wire_compatibility_version" : "7.17.0",
"minimum_index_compatibility_version" : "7.0.0"
},
"tagline" : "You Know, for Search"
}
添加新节点
获取token
在es01节点执行create-enrollment-token(可在任意已存在的节点上执行)
docker exec -it es01 /usr/share/elasticsearch/bin/elasticsearch-create-enrollment-token -s node
运行新节点
使用上面返回的token,作为第二个节点运行的参数
docker run -e ENROLLMENT_TOKEN="<token>" --name es02 --net elastic -it -m 1GB docker.elastic.co/elasticsearch/elasticsearch:8.12.1
关键配置
cluster.name: "docker-cluster"
network.host: 0.0.0.0
discovery.seed_hosts: ["192.168.228.2:9300"]
discovery.seed_hosts 指定在哪里查找已有集群的信息
查看节点
ELASTIC_PASSWORD="xxxx"
curl -k -u elastic:$ELASTIC_PASSWORD "https://localhost:9200/_cat/nodes?v=true""
返回
ip heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name
192.168.228.2 65 91 0 1.42 1.44 2.81 cdfhilmrstw * 804027f16295
192.168.228.3 34 100 0 1.42 1.44 2.81 cdfhilmrstw - 0975f7492948
集群健康
ELASTIC_PASSWORD="xxxx"
curl -k -u elastic:$ELASTIC_PASSWORD "https://localhost:9200/_cluster/health?pretty""
返回
{
"cluster_name" : "docker-cluster",
"status" : "green",
"timed_out" : false,
"number_of_nodes" : 2,
"number_of_data_nodes" : 2,
"active_primary_shards" : 1,
"active_shards" : 2,
"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
}
可会看到status 是green
集群原理
参考
集群内的原理 | Elasticsearch: 权威指南 | Elastic
新建、索引和删除文档 | Elasticsearch: 权威指南 | Elastic
准备
使用前面的方法,启动一个单节点的集群
空集群
如果我们只启动一个节点,没有包含任何索引和数据,看起来就是一个空集群,如下图
一个运行中的 Elasticsearch 实例称为一个节点,而集群是由一个或者多个拥有相同 cluster.name
配置的节点组成, 它们共同承担数据和负载的压力
当一个节点被选举成为 主 节点时, 它将负责管理集群范围内的所有变更,例如增加、删除索引,或者增加、删除节点等。 而主节点并不需要涉及到文档级别的变更和搜索等操作,所以单个主节点不会成为瓶颈
集群健康
Elasticsearch 的集群监控信息中包含了许多的统计数据,其中最为重要的一项就是 集群健康 , 它在 status
字段中展示为 green
、 yellow
或者 red
在我们的测试集群上执行命令,可以看到集群状态是green
ELASTIC_PASSWORD="xxxx"
curl -k -u elastic:$ELASTIC_PASSWORD "https://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" : 1,
"active_shards" : 1,
"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
}
status
字段指示着当前集群在总体上是否工作正常。它的三种颜色含义如下:
green
所有的主分片和副本分片都正常运行。
yellow
所有的主分片都正常运行,但不是所有的副本分片都正常运行。
red
有主分片没能正常运行。
添加索引
在elasticseach中,数据是保存在索引中,一个索引即一个数据集。索引实际上是指向一个或者多个物理 分片 的 逻辑命名空间
一个分片,保存了全部数据中的一部分, 是一个 Lucene 的实例,文档存储在分片内; 而实际对数据的操作,只需要指定索引,不需要关注分片
Elasticsearch 是利用分片将数据分发到集群内各处的。分片是数据的容器,文档保存在分片内,分片又被分配到集群内的各个节点里。 当你的集群规模扩大或者缩小时, Elasticsearch 会自动的在各节点中迁移分片,使得数据仍然均匀分布在集群里
一个分片可以是 主 分片或者 副本 分片。 索引内任意一个文档都归属于一个主分片,所以主分片的数目决定着索引能够保存的最大数据量。
一个副本分片只是一个主分片的拷贝。副本分片作为硬件故障时保护数据不丢失的冗余备份,并为搜索和返回文档等读操作提供服务。
在索引建立的时候就已经确定了主分片数,但是副本分片数可以随时修改。
我们在包含一个空节点的集群内创建名为 blogs
的索引, 3个主分片, 一个副本(每个主分片拥有一个副本分片)
PUT /blogs
{
"settings" : {
"number_of_shards" : 3,
"number_of_replicas" : 1
}
}
3个主分片都会分布在es01上, 如下图:
查看集群健康,可以看到如下结果:
{
"cluster_name" : "docker-cluster",
"status" : "yellow",
"timed_out" : false,
"number_of_nodes" : 1,
"number_of_data_nodes" : 1,
"active_primary_shards" : 4,
"active_shards" : 4,
"relocating_shards" : 0,
"initializing_shards" : 0,
"unassigned_shards" : 3,
"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" : 57.14285714285714
}
"active_primary_shards" : 4, 有一个是elasticseach自动创建的分片, 3个是blogs索引的分片
status是yellow表示全部 主 分片都正常运行(集群可以正常服务所有请求),但是 副本 分片没有全部处在正常状态。 实际上,所有3个副本分片都是 unassigned
—— 它们都没有被分配到任何节点。 在同一个节点上既保存原始数据又保存副本是没有意义的,因为一旦失去了那个节点,我们也将丢失该节点上的所有副本数据。
当前我们的集群是正常运行的,但是在硬件故障时有丢失数据的风险
启动第二个节点
使用前面的方法,启动第二个节点,并加入集群
查看集群健康,可以看到如下结果:
{
"cluster_name" : "docker-cluster",
"status" : "green",
"timed_out" : false,
"number_of_nodes" : 2,
"number_of_data_nodes" : 2,
"active_primary_shards" : 4,
"active_shards" : 8,
"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
}
可以看到节点数变为2, status变为green,表示所有主分片和副本分片都已被分配
分片数量为8, 其中1主1副是elasticsearch自己生成的, blogs所有有3个主分片,3个副本分片,3个副本全部在第2个节点上,如下图
再扩一个节点
按照上面的方法,再加入一个节点es03
查看集群健康
{
"cluster_name" : "docker-cluster",
"status" : "green",
"timed_out" : false,
"number_of_nodes" : 3,
"number_of_data_nodes" : 3,
"active_primary_shards" : 4,
"active_shards" : 8,
"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
}
节点数变为3, 分片数没变,但分片会在节点上重新分配
index shard prirep state docs store dataset ip node
.security-7 0 r STARTED 5 34.3kb 34.3kb 192.168.228.3 28f8f36bcf75
.security-7 0 p STARTED 5 34.3kb 34.3kb 192.168.228.2 804027f16295
blogs 0 r STARTED 0 249b 249b 192.168.228.3 28f8f36bcf75
blogs 0 p STARTED 0 249b 249b 192.168.228.2 804027f16295
blogs 1 p STARTED 0 249b 249b 192.168.228.2 804027f16295
blogs 1 r STARTED 0 249b 249b 192.168.228.4 fe1f3aae98ab
blogs 2 r STARTED 0 249b 249b 192.168.228.3 28f8f36bcf75
blogs 2 p STARTED 0 249b 249b 192.168.228.4 fe1f3aae98ab
可以看到blogs的第2分片的主分片、第1个分片的副本分配到了新节点192.168.228.4
如下图
把blogs的副本数调整为2
PUT /blogs/_settings
{
"number_of_replicas" : 2
}
blogs的总分片数变为9, 分布在3个节点上, 如下图:
分布式文档存储
路由一个文档到一个分片中
使用如下公式路由文档到分片
shard = hash(routing) % number_of_primary_shards
routing
是一个可变值,默认是文档的 _id
,也可以设置成一个自定义的值
新建、索引和删除文档
新建、索引和删除 请求都是 写 操作, 必须在主分片上面完成之后才能被复制到相关的副本分片,如下图
以下是在主副分片和任何副本分片上面 成功新建,索引和删除文档所需要的步骤顺序:
- 客户端向
Node 1
发送新建、索引或者删除请求。 - 节点使用文档的
_id
确定文档属于分片 0 。请求会被转发到Node 3
,因为分片 0 的主分片目前被分配在Node 3
上。 -
Node 3
在主分片上面执行请求。如果成功了,它将请求并行转发到Node 1
和Node 2
的副本分片上。一旦所有的副本分片都报告成功,Node 3
将向协调节点报告成功,协调节点向客户端报告成功。
取回一个文档
可以从主分片或者从其它任意副本分片检索文档 ,如下图
以下是从主分片或者副本分片检索文档的步骤顺序:
1、客户端向 Node 1
发送获取请求。
2、节点使用文档的 _id
来确定文档属于分片 0
。分片 0
的副本分片存在于所有的三个节点上。 在这种情况下,它将请求转发到 Node 2
。
3、Node 2
将文档返回给 Node 1
,然后将文档返回给客户端。
在处理读取请求时,协调结点在每次请求的时候都会通过轮询所有的副本分片来达到负载均衡