作者:刘晓国
在我们的实际部署中,我们的各个 node(节点)的能力是不一样的。比如有的节点的计算能力比较强,而且配有高性能的存储,速度也比较快,同时我们可能有一些 node 的能力稍微差一点,比如计算能力及存储器的速度都比较差一点。针对这两种情况,我们其实可以把这两种节点用来做不同的用途:运算能力较强的节点可以用来做 indexing(建立索引)的工作,而那些能力较差一点的节点,我们可以用来做搜索用途。我们可以把这两种节点分别叫做:
hot node:用于支持索引并写入新文档
warm node:用于处理不太频繁查询的只读索引
这种架构在 Elasticsearch 中,我们称之为 hot/warm 架构。
Hot node
我们可以使用 hot node 来做 indexing:
indexing 是 CPU 和 IO 的密集操作,因此热节点应该是功能强大的服务器
比 warm node 更快的存储
Warm node
对较旧的只读索引使用热节点:
倾向于利用大型附加磁盘(通常是旋转磁盘)
大量数据可能需要其他节点才能满足性能要求
Shard filtering
Shard filtering 在 Elasticsearch 中,我们可以利用这个能力来把我们想要的index放入到我们想要的 node 里。我们可以使用在elasticsearch.yml 配置文件中的:
node.attr 来指定我们 node 属性:hot 或是 warm。
在 index 的 settings 里通过 index.routing.allocation 来指定索引(index) 到一个满足要求的 node
为节点分配索引有三种规则:
就像上面的表格说明的一样:include 指的是至少包含其中的一个值;exclude 指的是不包含任何值;require 指的是必须包含里面索引的值。这些值实际上我们用来标识 node 的 tag。针对自己的配置这些 tag 可以由厂商自己标识。
标识 node
在上面的图中,我们标识 my_temp 属性为 hot 或是 warm,表明我们的 cluster 中分为两类:hot 或是 warm。在这里特别指出:这里的 my_temp,hot 及 warm 都是我们任意取的可以让我们记住的属性及名称。只要在使用时和 index.routing.allocation.include,index.routing.allocation.exclude 及 index.routing.allocation.require 中的值相对应即可。
配置索引的 settings
我们可以通过配置在 索引中的 settings 来分配我们的 index 到相应的具有哪些属性的 node 里,比如:
PUT logs-2019-03 { "settings": { "index.routing.allocation.require.my_temp": "hot" } }
在上面我们通过 logs-2019-03 的这个索引的 settings 来控制这个索引必须分配到具有 hot 属性的 node 里。
假如我们上面的 index logs-2019-03 由于一些原因不再是当前的用来做 indexing 的 index,比如我们可以通过 rollover API接口 来自动滚动我们的索引名字。我们可以通过如下的命令把该索引移动到 warm node 里:
PUT logs-2019-03 { "settings": { "index.routing.allocation.require.my_temp": "warm" } }
这样 Elasticsearch 会自动帮我们把 logs-2019-03 索引移动到 warm node 中,以便直供搜索之用。
例子
首先,我们我们按照如下的方式来做一个实验,虽然不能应用于实际的生产环境中:
1.按照 “如何在Linux,MacOS及Windows上进行安装Elasticsearch” 安装好自己的 Elasticsearh,但是不要运行 Elasticsearch
2.按照 “如何在Linux及MacOS上安装Elastic栈中的Kibana” 安装好自己的 Kibana
在我们完成上面的两个安装后,我们分别打开两个 terminal,然后分别在两个 terminal 中运行如下的指令:
./bin/elasticsearch -E node.name=node1 -E node.attr.data=hot -Enode.max_local_storage_nodes=2
上面的指令运行一个名字叫做 node1 的,data 属性为 hot 的 node。
./bin/elasticsearch -E node.name=node2 -E node.attr.data=warm -Enode.max_local_storage_nodes=2
上面的指令运行一个名字叫做 node2 的,data 属性为 hot 的 warm。
我们可以在Kibana里查看我们的nodes:
我们可以看出来有两个 node 正在运行:node1 及 node2。如果我们想了解这两个 node 的更多属性,我们可以打入如下的命令:
GET _cat/nodeattrs?v&s=name
显示的结果为:
我们可以看到 node 被标识为 hot node,而 node2 被标识为 warm node。
接下来,我们运用我们上面命令来把我们的 logs-2019-03 置于我们的 hot node 里。我们可以通过如下的命令:
PUT logs-2019-03 { "settings": { "number_of_shards": 1, "number_of_replicas": 0, "index.routing.allocation.require.data": "hot" } }
运行上面的结果后,可以通过如下的命令来查看:
GET _cat/shards/logs-*?v&h=index,shard,prirep,state,node&s=index,shard,prirep
显示的结果为:
从上面我们可以看出来我们的 logs-2019-03 是分配到 node1上面的。
假如我们由于某种原因,想把 logs-2019-03 分配到 node2 上面,那么该怎么做呢?我们可以通过如下的命令来实现:
PUT logs-2019-03/_settings { "index.routing.allocation.require.data": "warm" }
运行上面的指令显示的结果是:
显然我们 logs-2019-03 已经成功地移到 node2 了。
针对硬件的 shard filtering
上面我们说了,对于 node.attr 来说,我们可以添加任意的属性。在上面的我们已经使用 hot/warm 来标识我们的 my_temp 属性。其实我们也可以同时定义一些能标识硬件的属性 my_server,这个属性值可以为 small,medium 及 large。有多个属性组成的集群就像是如下的结构:
那么这样的集群里的每个 node 可能具有不同的属性。我们可以通过如下的方法来分配索引到同时具有两个或以上属性的 node 里:
PUT my_index1 { "settings": { "number_of_shards": 2, "number_of_replicas": 1, "index.routing.allocation.include.my_server": "medium", "index.routing.allocation.require.my_temp": "hot" } }
如上所示,我们把我们的 my_index1 分配到这么一个 node:这个 node 必须具有 hot 属性,同时也具有 medium 的属性。针对我们上面显示的图片,只有 node1 满足我们的要求。
总结:在今天的这篇文章中,我们介绍了如何使用 shard filtering 来控制我们的 index 的分配。在实际的操作中,可能大家会觉得麻烦一点,因为这个需要我们自己来管理这个。这个技术可以和我之前的文章 “Elasticsearch: rollover API” 一起配合使用。Elasticsearch 实际已经帮我做好了。在接下来的文章里,我会来介绍如何使用 Index life cycle policy 来自动管理我们的索引。