· 更多精彩内容,请下载阅读全本《Elastic Stack实战手册》
创作人:张刘毅
审稿人:吴斌
Elasticsearch 集群天然支持横向水平扩展,因此当业务规模扩大、对集群产生读写压力时,增加节点总是运维人员的“懒人选择”。但随着节点数增多,集群主节点要维护的 meta 信息也随之增多,这会导致集群更新压力增大,甚至无法提供正常服务。 另外每个企业的数据中心都需要有灾备方案,在集群间同步数据,因为单点集群会存在隐患。
鉴于此,Elastic官方提供了跨集群操作。主要包括:
(1)跨集群搜索(CCS):允许配置多个远程集群并且在所有已配置的集群中实现联合搜索。
(2)跨集群复制(CCR):允许跨多个集群复制索引,适合于做灾备方案和数据本地化场景。
跨集群配置
跨集群操作有两种配置模式连接远程的集群:嗅探模式(Sniff mode)或者代理模式(Proxy mode)。
- 在嗅探模式下,我们使用集群名称和种子节点列表注册远程集群。注册后,集群状态将被种子节点获取,该模式要求本地群集可以访问网关节点的发布地址。
- 在代理模式下,使用集群名称和单个代理地址注册远程集群。代理模式不需要远程集群节点具有可访问的发布地址。
我们可以在 Kibana 上动态配置远程集群,也可以在各个节点的 elasticsearch.yml 文件的上配置。
动态配置远程集群
我们在 Kibana 上使用 cluster update settings API 为每个节点动态配置远程集群。
例如:
PUT _cluster/settings
{
"persistent": {
"cluster": {
"remote": {
"cluster_one": {
"seeds": [
"127.0.0.1:9300"
],
"transport.ping_schedule": "30s"
},
"cluster_two": {
"mode": "sniff",
"seeds": [
"127.0.0.1:9301"
],
"transport.compress": true,
"skip_unavailable": true
},
"cluster_three": {
"mode": "proxy",
"proxy_address": "127.0.0.1:9302"
}
}
}
}
}
上面的配置中,当前集群是 cluster_one,一起联合远程访问的集群 cluster_two、cluster_three。其中 cluster_two 的连接方式是嗅探模式,cluster_three 的连接方式是代理模式,代理地址是 "127.0.0.1:9302"。
其中:
- transport.compress:网络传输的压缩参数
- transport.ping_schedule :集群内部通信(tcp)的访问频率
- skip_unavailable:默认情况下如果请求中的任何集群都不可用则会返回错误。如果跳过不可用的集群,可以将 skip_unavailable 设置为 true。
以上这些参数是可以动态调整的,但必须要包括 seed 列表或者代理地址。
我们如果想关闭压缩、将 ping_schedule 由 30s 改成 60s可以通过如下示例方式
PUT _cluster/settings
{
"persistent": {
"cluster": {
"remote": {
"cluster_one": {
"seeds": [
"127.0.0.1:9300"
],
"transport.ping_schedule": "60s"
},
"cluster_two": {
"mode": "sniff",
"seeds": [
"127.0.0.1:9301"
],
"transport.compress": false
},
"cluster_three": {
"mode": "proxy",
"proxy_address": "127.0.0.1:9302",
"transport.compress": true
}
}
}
}
}
静态配置远程集群
在节点的 elasticsearch.yml 中配置远程连接,只有在 YAML 文件中设置的节点,才能连接到远程集群,并处理远程集群请求。
举例
cluster:
remote:
cluster_one:
seeds: 127.0.0.1:9300
transport.ping_schedule: 30s
cluster_two:
mode: sniff
seeds: 127.0.0.1:9301
transport.compress: true
skip_unavailable: true
cluster_three:
mode: proxy
proxy_address: 127.0.0.1:9302
其中,cluster_one,cluster_two 和 cluster_three 是表示与每个集群的连接的集群名称,用于区分本地索引和远程索引。
跨集群搜索
跨集群搜索可以针对一个或多个远程集群,运行单个搜索请求。例如,我们可以使用跨集群搜索,来过滤和分析存储,在不同数据中心的集群中的日志数据。
在5.3.0之前的版本,Elastic 官方提供了 Tribe Node 实现多集群访问的解决方案。
Tribe Node 是以 Client Node 的角色添加到集群中。但是由于不保留集群的 meta 信息,每次重启需要重新加载初始化。因此,在5.3版本中 Elastic 官方提供了 CCS 的功能,允许集群中的任何节点可以联合查询。
快速入门
下面以两个集群的跨集群搜索为例。我们预先启动了两个集群:cluster1、cluster2,当前集群是 cluster1。现在的任务是联合远程访问的集群 cluter2 进行跨集群搜索。
我们分别在两个集群上动态配置 remote cluster。
注意:在 seeds 列表中填写的是集群节点间通信的 TCP 端口而不是 HTTP 端口。
PUT _cluster/settings
{
"persistent": {
"cluster": {
"remote": {
"cluster_one": {
"seeds": [
"192.168.2.2:9300"
]
},
"cluster_two": {
"seeds": [
"192.168.2.2:9500"
]
}
}
}
}
}
在 cluster1 中插入数据
PUT esfighttogether/_doc/1
{
"teamname":"team 10"
}
在 cluster2 中插入数据
PUT esfighttogether/_doc/1
{
"teamname":"team 1"
}
PUT esfighttogether/_doc/2
{
"teamname":"team 7"
}
在两个集群上分别验证数据。因为写入时 Elasticsearch 自带的默认分词器会对数据进行分词,我们通过 team 就可以查询到所有数据。
查询语句如下:
GET esfighttogether/_search
{
"query": {
"match": {
"teamname": "team"
}
}
}
执行跨集群搜索
GET cluster_one:esfighttogether,cluster_two:esfighttogether/_search?timeout=5m
{
"query": {
"match": {
"teamname": "team"
}
}
}
如上图所示,通过 CCS 查询到 3 条数据:cluster_one 的一条数据 team 10 以及 cluster_two 的两条数据 team 1 和 team 7,和之前写入的数据一致。
跨集群复制
跨集群复制是将特定索引,从一个 Elasticsearch 集群复制到另外的集群。
一般用于以下场景:
- 灾备:数据中心服务中断时,可以继续响应用户的搜索请求,防止用户大的查询影响到写入吞吐
- 数据本地化:将数据复制到更靠近用户的位置以降低搜索延迟
跨集群复制使用主动-被动模型,我们将索引写入领导者索引,数据会被复制到一个或多个只读跟随者索引。在将跟随者索引添加到集群之前,我们需要配置包含领导者索引的远程集群。
当领导者索引有写入请求时,跟随者索引从远程集群上的领导者索引中拉取增量数据。我们可以手动创建跟随者索引,或配置自动跟随模式(auto-follow patterns),创建跟随者索引。
我们可以单向或双向配置 CCR:
- 在单向配置中,一个集群仅包含领导者索引,而另一个集群仅包含跟随者索引。
- 在双向配置中,每个集群都包含领导者索引和跟随者索引
快速入门
我们在服务器上启动两个集群来模拟不同地区数据中心的集群:
- “cluster1”:在端口 9200 上运行。我们会将文档从 cluster1 复制到 cluster2。
- “cluster2”:在端口 9400 上运行。cluster2 将维护一个来自 cluster1 的复制索引。
配置远程集群
我们选择 CCR 的单向配置,因此 CCR 是基于拉取模式,所以我们只需要确保 cluster2 连接到cluster1 ,而不需要指定从 cluster2 到 cluster1 的连接。
下面让我们通过 cluster2 上的 API 调用来定义 cluster1:
PUT /_cluster/settings
{
"persistent": {
"cluster": {
"remote":{
"cluster1":{
"seeds":["192.168.2.2:9300"]
}
}
}
}
}
Kibana 中远程集群管理的 UI,单击左侧导航面板中的 “Management”(齿轮图标),然后点击 “Stack Management” ,导航到 Elasticsearch 部分中的 “Remote Clusters”(远程集群)。
创建要复制的索引
PUT esfightalone
{
"settings": {
"index": {
"number_of_shards": 1,
"number_of_replicas": 0,
"soft_deletes": {
"enabled": true
}
}
},
"mappings": {
"properties": {
"name": {
"type": "keyword"
}
}
}
}
CCR 的 Leader 索引需要使用软删除(soft_deletes),无论何时删除或更新现有文档,都可以将操作历史记录保留在领导者分片上,等重新操作历史记录时,供追随者分片任务使用。
当追随者分片从领导者复制数据时,会在领导者分片上留下标记,这样领导者就知道追随者在历史记录中的所在位置。基于这些标记,领导者分片将会保留这些操作,直到分片历史记录保留到设定时间结束(默认为 12 个小时)。
我们已经为远程集群创建了一个别名,并创建了一个我们要复制的索引,接下来我们启动复制。在 cluster2 上,执行:
PUT /esfightalone-copy/_ccr/follow
{
"remote_cluster" : "cluster1",
"leader_index" : "esfightalone"
}
注意,复制索引是只读的,不能接受写操作。至此,我们已配置了要从一个 Elasticsearch 集群复制到另一个集群的索引。
测试 CCR 复制
我们在 cluster1 上写入数据:
POST /esfightalone/_doc
{
"name" :"team 1"
}
然后在 cluster2 上查询,验证索引数据是否同步,发现此时数据已实时同步到 cluster2 中了:
GET /esfightalone-copy/_search
CCR 属于 Elastic 官方的白金付费(Platinum License)的功能。一般企业还是会选择自研数据同步工具,来同步集群间的数据。
不过,需要体验的小伙伴可以在 Elastic 官网或阿里云 Elasticsearch 申请 30 天免费使用或者在自己的本地安装中启用试用功能。
创作人简介:
张刘毅,存储研发工程师,曾经做过 AI 大数据平台研发,负责过 80+ES 集群。目前专
注于生物医药和大数据。
博客: https://blog.csdn.net/dtzly