一、跨集群复制原理
1、跨集群复制
跨集群复制即CCR,是一种能够实现数据迁移、数据备份、降低访问延迟的高可用解决方案。跨集群复制采用的是一个主备的架构模型。在主集群中创建一系列leader索引,在备集群中通过主动Pull方式复制数据到follower索引中,且follower索引为只读索引。
2、互为主备的CCR架构
CCR不仅支持单向同步,还支持双向数据同步,即两个ES集群互为主备。
如图2所示,集群A中部分索引为leader索引,部分索引为follower索引。集群B中部分索引为follower索引,部分索引为leader索引。形成一种双向同步的网络架构。集群B中的follower索引通过CCR机制同步集群A中的leader索引数据。集群A中的follower索引通过CCR机制同步集群B中的leader索引数据。由于follower必须为只读索引,因此,一个索引无法既为leader索引,又为follower索引。即在集群维度上看是双向同步,但是在索引维度上,依然是单向同步。
3、CCR数据同步机制
CCR的数据同步是分片维度的。即当一个follower索引创建时,follower索引上的每个主分片会定期拉取leader索引分片的更新数据。也就是说,follower索引的主分片个数必须要和leader索引的主分片个数保持一致。这样能够保障在leader索引上的所有写操作都能够被复制到follower索引中,这些写操作包括create、update、delete文档等。
如图3所示,follower分片发起的Pull请求会被主分片或者副本分片进行处理。当follower分片发送一个read请求时,leader分片会判断本地是否有新的未同步过的写操作。如果没有未同步过的新操作,leader分片会等待一段时间,如果在等待的这段时间里依然没有新的同步(写)操作,则返回空信息给follower分片。follower分片会update本地的分片统计信息并立即发送另一个新的pull请求给leader分片。
该数据通信模型能够确保在两个集群的leader/follower分片之间的网络连接保持长期可用。如果follower分片发起的pull请求由于网络原因导致的失败,则follower分片会无限循环进行重试,直到成功为止。如果是由于其他原因导致的失败,如leader分片被设置为只读等,则会中止,需要手工恢复。
手工恢复索引同步可直接在Kibana上进行操作,即选择Cross-Cluster Replication 然后点击Follower indices tab,选择需要手工恢复的follower 索引,选择Manage follower index>Pause replication,如图4所示。
这时候follower索引状态变成中止状态,然后再选择该索引,点击Resume replication,如图5所示。
4、CCR数据更新
follower在建立ccr过程中,是只读索引。因此,我们无法再对follower索引进行任何的数据写入,包括修改索引的mapping和alias等信息。只能通过leader索引的更新再同步后完成。follower索引并不会将leader索引上的任何更新操作都进行同步。例如修改了leader索引的副本个数,follower索引并不会做相应修改。详细信息可参照下图6:
需要注意的是:如果我们对leader索引进行一个静态settings的设置,例如修改索引的index.soft_deletes.retention_lease.period属性,则follower索引会执行re-open操作。即先close 索引,然后执行update settings操作,更新完成后再次打开索引。因此在re-open期间,follower索引读写均不可用。
5、follower索引初始化
follower索引只有在执行完初始化工作后才能接受查询和数据同步操作。follower的初始化可以理解为是leader索引的全量同步,即 “远程恢复过程”。该过程是通过全量拷贝leader索引主分片上的数据到follower集群上进行恢复。因此远程恢复是一个网络IO密集型的操作,主要工作就是将leader索引上的所有的Lucene的segment文件全量拷贝到follower集群上,然后进行恢复,有点类似于snapshot的恢复机制。默认情况下,一次Recovery请求会同时拉取5个1MB的segment文件块,且默认速度为40mb/s,可通过如下参数进行调整,详细信息可参考官方文档。
表1. Cross-cluster replication settings汇总
CCR可动态调整的参数 | 参数说明 |
---|---|
ccr.indices.recovery.max_bytes_per_sec | 限制每个节点的出入流量,默认40mb/s |
ccr.indices.recovery.max_concurrent_file_chunks | 控制follower索引初始化恢复可并行发送的文件块请求数,默认是5,最大为10 |
ccr.indices.recovery.chunk_size | 控制follower索引文件传输的块大小,默认1mb |
ccr.indices.recovery.recovery_activity_timeout | 控制leader集群打开内存资源接收follower集群恢复请求的超时时间,默认60s |
ccr.indices.recovery.internal_action_timeout | 控制ccr远程恢复过程中单个网络请求的超时时间,默认60s |
6、soft_delete机制
CCR同步机制是通过Lucene底层的sofe_delete来实现的。因此需要确保leader索引是开启soft_delete属性的,7.0版本之后索引的soft_delete属性是默认开启的,7.0版本之前是默认关闭的。因此如果是使用如6.8.2等较早版本作为CCR的Leader集群,则需要在创建索引时手动开启soft_delete属性,或者在索引模版中进行开启。另外soft_delete属性为static setting,不支持通过index/_settings进行动态修改,如果需要对存量的索引开启soft_delete,则必须进行reindex操作。
硬删除和软删除
在ES中当我们update一条doc时,其内部的实现其实是先insert一条doc,然后将原来的doc执行delete操作,这里并不会真正的将older version的doc从磁盘上删除,而是对其做了标记处理,client端在执行search时候,会对其进行过滤,不返回给client。然后在segment merge的时候才会真正的将这些标记了删除的doc从磁盘中彻底删除。这种删除操作我们称之为硬删除。ES之所以不使用硬删除做peer-recovery和CCR,其主要原因就是因为这些被标记了删除的doc会在merge时被清理,这就无法在副本分片或者follower索引上进行操作重放了。
soft_delete是Lucene中实现的一个特性,其原理是对doc额外新增了一个字段,以标记该doc是否被软删除。默认是0,当一个doc被软删除后,则将该字段置为1。并且在segment merge的时候病不会立即清理被软删除了的doc,而是会保留一定的时间(默认是12小时),在该保留期限内, merge操作不会清理,超过了该保留期限后,merge操作才会真正将软删除的doc从磁盘中彻底删除。ES则正是使用了这一特性来实现集群内部的peer-recovery和集群之间的CCR功能。
将同时将该delete的doc的soft_delete字段设置为1。这样在执行查询的时候就可以通过soft_delete字段进行过滤,将软删除的doc排除掉不返回给client。但是在peer-recovery和CCR的时候则是可以获取到被标记了soft_delete的doc并在follower索引上进行重放的。
二、CCR双向同步实践
CCR既支持单向同步,也支持双向同步。双向同步是指集群维度,但是实际上从索引维度上来看的话依然是单向同步。
如上图7所示,ES集群A和ES集群B组成互为主备架构,即ES集群A中部分索引为leader索引,集群B中follower索引通过CCR机制从集群A中同步数据。同理,ES集群B中部分索引为leader索引,集群A中follower索引通过CCR机制从集群B中同步数据。业务通过“双写”或代理等机制同时向两个集群中的leader索引中写入数据。这样即能达到互为主备的高可用容灾效果。
当某一数据中心的ES集群出现故障时,业务端可自动调整。例如业务侧检测到集群A不可用时,则自动向集群B中新建索引并写入数据,且只从集群B中查询数据,可保障数据的完整性。下面我们以双向同步为例,手动搭建CCR的运行环境。
1、集群环境准备
表2. CCR双向同步集群信息汇总表
ES集群名称 | 集群id | 版本 |
---|---|---|
集群A | es-dhiewpz2 | 7.10.1 |
集群B | es-9vkapeic | 7.10.1 |
2、搭建CCR双向同步
主要步骤如下:
2.1 配置集群A为Follower,集群B为Leader
效果:集群A自动同步集群B上的部分索引
1)配置Reomte Clusters
路径:Stack Management-Data-Remote Clusters-Add a remote cluster
详细配置信息如下:
点击完成后会自动跳转到Remote Clusters列表页,这里可以看到连接状态为Connected,说明Remote Clusters配置完成了。
2)配置Auto follower pattern
路径:Stack Management-Data-Cross Cluster Replication-Create an auto-follow pattern
具体配置信息如下:
点击Create后即跳转到auto-follow pattern的列表页。
也可在kibana上执行API查看配置的auto-follow信息。
3)测试index同步
在Leader集群B中创建一个索引,索引名称为:ilm-test-index。
然后在Follow集群A的索引管理页面可以看到该索引已同步完成,通过CCR方式创建的索引,会在索引后面加一个“Follower标记”,表明该索引为跟随者索引,不可接受写入。
2.2 配置集群B为Follower,集群A为Leader
效果:集群B自动同步集群A上的部分索引。
这里的配置Remote Cluster和auto follower pattern步骤和上面的一致。
3、跨集群复制需要注意的问题
3.1 关于双向同步版本问题
CCR双向同步,必须要保证双向同步的两个集群版本基本保持一致,如集群A为6.8.2,集群B为6.8.6是没有问题的,即小版本可以有差别,具体版本矩阵可参考官方文档:
3.2 多Type问题
如果Leader集群是7.x之前的版本,则通过多type方式向集群中写入数据时,会导致follower集群同步任务暂停并失败。
如通过下面的api向Leader集群中写入一条数据:
代码语言:javascript复制PUT gd_sales/doc
{
"name":"json",
"age":40
}
则会在follower集群出现同步失败的日志:
查询follower索引同步状态可以看到异常信息:
代码语言:javascript复制GET gd_sales/_ccr/stats
解决办法为使用_doc单type进行写入。
三、跨集群复制总结
以上我们分别从CCR的基本原理和动手实践向大家介绍了Elasticsearch的跨集群复制功能,并总结了在生产实践中使用跨集群复制功能时需要注意的问题及解决方案,希望对大家有帮助。