常见的数据库都会提供备份的机制,以解决在数据库没法使用的状况下,能够开启新的实例,而后经过备份来恢复数据减小损失。虽然 Elasticsearch 有良好的容灾性,但因为如下缘由,其依然须要备份机制。html
Elasticsearch 作备份有两种方式,一是将数据导出成文本文件,好比经过 elasticdump、esm 等工具将存储在 Elasticsearch 中的数据导出到文件中。二是以备份 elasticsearch data 目录中文件的形式来作快照,也就是 Elasticsearch 中 snapshot 接口实现的功能。第一种方式相对简单,在数据量小的时候比较实用,当应对大数据量场景效率就大打折扣。咱们今天就着重讲解下第二种备份的方式,即 snapshot api 的使用。git
备份要解决备份到哪里、如何备份、什么时候备份和如何恢复的问题,那么咱们接下来一个个解决。github
在 Elasticsearch 中经过 repository 定义备份存储类型和位置,存储类型有共享文件系统、AWS 的 S3存储、HDFS、微软 Azure的存储、Google Cloud 的存储等,固然你也能够本身写代码实现国内阿里云的存储。咱们这里以最简单的共享文件系统为例,你也能够在本地作实验。数据库
首先,你要在 elasticsearch.yml 的配置文件中注明能够用做备份路径 path.repo ,以下所示:json
path.repo: ["/mount/backups", "/mount/longterm_backups"]
配置好后,就可使用 snapshot api 来建立一个 repository 了,以下咱们建立一个名为 my_backup 的 repository。api
PUT /_snapshot/my_backup { "type": "fs", "settings": { "location": "/mount/backups/my_backup" } }
以后咱们就能够在这个 repository 中来备份数据了。微信
有了 repostiroy 后,咱们就能够作备份了,也叫快照,也就是记录当下数据的状态。以下所示咱们建立一个名为 snapshot_1 的快照。网络
PUT /_snapshot/my_backup/snapshot_1?wait_for_completion=true
wait_for_completion 为 true 是指该 api 在备份执行完毕后再返回结果,不然默认是异步执行的,咱们这里为了马上看到效果,因此设置了该参数,线上执行时不用设置该参数,让其在后台异步执行便可。异步
执行成功后会返回以下结果,用于说明备份的状况:elasticsearch
{ "snapshots": [ { "snapshot": "snapshot_1", "uuid": "52Lr4aFuQYGjMEv5ZFeFEg", "version_id": 6030099, "version": "6.3.0", "indices": [ ".monitoring-kibana-6-2018.05.30", ".monitoring-es-6-2018.05.28", ".watcher-history-7-2018.05.30", ".monitoring-beats-6-2018.05.29", "metricbeat-6.2.4-2018.05.28", ".monitoring-alerts-6", "metricbeat-6.2.4-2018.05.30" ], "include_global_state": true, "state": "SUCCESS", "start_time": "2018-05-31T12:45:57.492Z", "start_time_in_millis": 1527770757492, "end_time": "2018-05-31T12:46:15.214Z", "end_time_in_millis": 1527770775214, "duration_in_millis": 17722, "failures": [], "shards": { "total": 28, "failed": 0, "successful": 28 } } ] }
返回结果的参数意义都是比较直观的,好比 indices 指明这次备份涉及到的索引名称,因为咱们没有指定须要备份的索引,这里备份了全部索引;state 指明状态;duration_in_millis 指明备份任务执行时长等。
咱们能够经过 GET _snapshot/my_backup/snapshot_1
获取 snapshot_1 的执行状态。
此时若是去 /mount/backups/my_backup 查看,会发现里面多了不少文件,这些文件其实都是基于 elasticsearch data 目录中的文件生成的压缩存储的备份文件。你们能够经过 du -sh . 命令看一下该目录的大小,方便后续作对比。
经过上面的步骤咱们成功建立了一个备份,但随着数据的新增,咱们须要对新增的数据也作备份,那么咱们如何作呢?方法很简单,只要再建立一个快照 snapshot_2 就能够了。
PUT /_snapshot/my_backup/snapshot_2?wait_for_completion=true
当执行完毕后,你会发现 /mount/backups/my_backup 体积变大了。这说明新数据备份进来了。要说明的一点是,当你在同一个 repository 中作屡次 snapshot 时,elasticsearch 会检查要备份的数据 segment 文件是否有变化,若是没有变化则不处理,不然只会把发生变化的 segment file 备份下来。这其实就实现了增量备份。
elasticsearch 的资深用户应该了解 force merge 功能,便可以强行将一个索引的 segment file 合并成指定数目,这里要注意的是若是你主动调用 force merge api,那么 snapshot 功能的增量备份功能就失效了,由于 api 调用完毕后,数据目录中的全部 segment file 都发生变化了。
另外一个就是备份时机的问题,虽然 snapshot 不会占用太多的 cpu、磁盘和网络资源,但仍是建议你们尽可能在闲时作备份。
所谓“养兵千日,用兵一时”,咱们该演练下备份的成果,将其恢复出来。经过调用以下 api 便可快速实现恢复功能。
POST /_snapshot/my_backup/snapshot_1/_restore?wait_for_completion=true { "indices": "index_1", "rename_replacement": "restored_index_1" }
经过上面的 api,咱们能够将 index_1 索引恢复到 restored_index_1 中。这个恢复过程彻底是基于文件的,所以效率会比较高。
虽然咱们这里演示的是在同一个集群作备份与恢复,你也能够在另外一个集群上链接该 repository 作恢复。咱们这里就不作说明了。
因为 Elasticsearch 版本更新比较快,所以你们在作备份与恢复的时候,要注意版本问题,同一个大版本之间的备份与恢复是没有问题的,好比都是 5.1 和 5.6 之间能够互相备份恢复。但你不能把一个高版本的备份在低版本恢复,好比将 6.x 的备份在 5.x 中恢复。而低版本备份在高版本恢复有必定要求:
1) 5.x 能够在 6.x 恢复
2) 2.x 能够在 5.x 恢复
3) 1.x 能够在 2.x 恢复
其余跨大版本的升级都是不可用的,好比1.x 的没法在 5.x 恢复。这里主要缘由仍是 Lucene 版本问题致使的,每一次 ES 的大版本升级都会伴随 Lucene 的大版本,而 Lucene 的版本是尽可能保证向前兼容,即新版能够读旧版的文件,但版本跨越太多,没法实现兼容的状况也在所不免了。
本文只是简单对 snapshot 功能作了一个演示,但愿这足够引发你的兴趣。若是你想进一步深刻的了解该功能,好比备份的时候如何指定部分索引、如何查询备份和还原的进度、如何跨集群恢复数据、如何备份到 HDFS 等,能够详细阅读官方手册https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshots.html,若是在使用的过程当中遇到了问题,欢迎留言或者加我微信(rockybean)讨论。