
Es每個節點上只會存儲部分的數據,而使用replicas機制已經對數據進行冗余備份,但是對生產的Es進行全量(第一次為全量)和增量數據災備是非常有必要的。一般會選擇將數據災備到共享文件系統中。但是最終決定使用每日(每周,取決于數據的重要性)定時任務將共享文件的災備數據打tar包并同步到阿里云的OSS的特定bucket中,即災備的災備。雖然定時的快照為增量數據,但是只有es清除那些是增量數據哪些是第一次的基礎數據,所以每天需要將全量數據打包并同步到OSS,若OSS只存儲5天的全量數據,則在每天同步完之后需要清除5天前的全量數據包。
(資料圖片僅供參考)
若發生異常需要恢復數據的時候,首先從共享文件系統直接進行快照恢復,共享文件系統不可用則可以直接從OSS中拉取數據,解壓并替換共享目錄下的數據,再執行快照恢復命令。
1、災備
基于Es的snapshot API可以對集群災備,但是需要先創建倉庫,并且在倉庫中創建快照(第一次為全量數據,后續為增量數據),而在快照區中分索引。以下是倉庫可選擇的類型,默認會選擇共享文件系統(并且一般會使用sshfs,并且會遇到坑):
1、共享文件系統,比如 NAS
2、Amazon S3
3、HDFS (Hadoop 分布式文件系統)
4、Azure Cloud
1、sshfs共享文件系統創建
安裝sshfs:
yum install sshfs
在每個節點下配置共享文件目錄:
sudo sshfs -o allow_other -o nonempty root@192.168.10.11:/data/sshfs-repository/ /data/elasticsearch-repository -p 61822(說明:-o allow_other所有用戶都可以讀寫,root用戶使用ssh將本地的文件目錄/data/elasticsearch-repository共享到遠程IP(或域名)為192.168.10.11上的/data/sshfs-repository/目錄,若ssh段端口不為22需要使用-p 61822指定,而由于可能存在已經運行過命令,已經掛在過則目錄下可能存在文件則可以使用-o nonempty告訴其可以忽略目錄下的文件進行刪除或修改),如下:
若掛在錯了,或者需要刪除已經掛在的點,可以使用(不要自行刪除文件或目錄的方式):
fusermount -uz /data/elasticsearch-repository(后面的路徑為本地路徑)
測試,可以在每個節點服務器上運行一下命令檢測用戶是否對本地的共享文件目錄擁有寫權限:
sudo -u elasticsearch touch /data/elasticsearch-repository/test
2、es配置
將集群中每個節點下的elasticsearch.yml中添加倉庫路徑的白名單列表:
path.repo: /mnt 或 path.repo: [“/path1” , “path2” ]
3、倉庫創建
需要根據自己的網絡設置快照或恢復的限流參數,只要不能影響正常的數據索引和查詢聚合請求。
// 使用GET請求用于創建,POST請求若存在則為修改
POST _snapshot/my_backup/ {
"type": "fs", // 倉庫類型為共享文件系統
"settings": {
"location": "/mnt", // 倉庫路徑,需要與sshfs的遠程目錄一致,并在需要在es集群的白名單中存在
"max_snapshot_bytes_per_sec" : "50mb",
// 當快照數據進入倉庫時,這個參數控制這個過程的限流情況。默認是每秒 20mb 。
"max_restore_bytes_per_sec" : "50mb"
// 當從倉庫恢復數據時,這個參數控制什么時候恢復過程會被限流以保障你的網絡不會被占滿。默認是每秒 `20mb`。
}
}
4、快照相關操作
1、快照的創建
創建快照,默認為異步執行,添加參數wait_for_completion則為同步等待,如下:
PUT _snapshot/my_backup/snapshot_1?wait_for_completinotallow=true
2、索引配置
由于es集群環境中一般除了業務數據索引外還會有kibana或監控的索引,所以一般會指定需要快照的索引,如下:
PUT _snapshot/my_backup/snapshot_2{
"indices": "index_1,index_2"
}
3、獲取快照相關信息
獲取某倉庫下的一個或索引的快照信息,如下:
GET _snapshot/my_backup/snapshot_2
或
GET _snapshot/my_backup/_all
4、監控快照進度
如果快照距離上一次的數據增量比較大或第一次執行快照,則快照執行的時間可能會比較長,可以使用以下api對其執行狀態進行查看(由于使用_status查看的線程和執行快照的線程屬于同一類線程池,所以速度回比較慢):
GET _snapshot/my_backup/snapshot_3
或
GET _snapshot/my_backup/snapshot_3/_status
5、快照取消或刪除
因為快照是增量的,有可能很多快照依賴于過去的段,索引不能使用人工等方式進行刪除操作,而需要使用Es 的delete API。由于快照的過程會比較長,若在執行時需要取消,可以使用與刪除一樣的API,只是若在還在執行快照的過程中接收到取消操作,則會先中斷快照進行,再將已經執行的數據進行刪除,命令如下:
DELETE _snapshot/my_backup/snapshot_2
2、恢復
1、使用快照恢復數據
由于回復工程默認為異步恢復,可以使用wait_for_completinotallow=true同步獲取結果,并且可以使用indices參數指定需要恢復的索引的名稱,并且可以使用rename_pattern參數查找所提供的模式能匹配上的正在恢復的索引(沒怎么理解),使用rename_replacement參數重命名回復后的索引名稱,如下:
POST /_snapshot/my_backup/snapshot_1/_restore?wait_for_completinotallow=true
{
"indices": "index_1",
"rename_pattern": "index_(.+)",
"rename_replacement": "restored_index_$1"
}
2、恢復過程監控
從倉庫恢復數據借鑒了 Elasticsearch 里已有的現行恢復機制。 在內部實現上,從倉庫恢復分片和從另一個節點恢復是等價的,使用了Es的recover API,如下:
GET restored_index_3/_recovery
3、取消恢復
若在執行過程中需要撤銷恢復操作,可以執行刪除操作即可,若接收到刪除命令首先會停止恢復操作,再將已恢復是數據進行刪除,命令如下:
DELETE /restored_index_3
3、ES snapshot java API
若想定時為es集群索引創建快照,則可以使用java定時任務創建,如下:
private static final String BASE_SNAPSHOT = "snapshot_geleevr_";
/**
* 每天執行Es集群快照
*
* @throws Exception
*/
//@Scheduled(crnotallow="0 0 1 * * ?")
//@Scheduled(fixedRate=30000000)
public void execute() throws Exception {
TransportClient client = ESClient.me();
CreateSnapshotRequestBuilder builder = CreateSnapshotAction.INSTANCE.newRequestBuilder(client);
String snapshotName = BASE_SNAPSHOT + UTCDateUtil.userFormat(new Date());
long start = System.currentTimeMillis();
// 快照執行的時間可能比較長,而且不可控(只能定時通過status api查詢),所以異步獲取狀態
builder.setIndices(ESConfig.COMPANY, ESConfig.ANALYZE)
.setRepository(ESConfig.ES_REPOSITORY)
.setSnapshot(snapshotName)
.execute(new ActionListener
@Override
public void onResponse(CreateSnapshotResponse response) {
long end = System.currentTimeMillis();
long seconds = (long) ((end - start)/1000);
logger.info("task of snapshot {} is sync sussess , total time is {} seconds !", snapshotName, seconds);
}
@Override
public void onFailure(Exception e) {
long end = System.currentTimeMillis();
long seconds = (long) ((end - start)/1000);
logger.error("task of snapshot {} is failure , total time is {} seconds !", snapshotName, seconds);
}
});
}
4、遇到的問題
1、doesn"t match any of the locations specified by path.repo because this setting is empty
在為es集群環境做災備和恢復時候,首先需要創建創建一個倉庫,并往倉庫中存放快照(每個快照中會區分不同的索引)。但是在創建倉庫的時候,要求倉庫的地址必須在每個集群環境中的elasticsearch.yml中進行配置(相當于一個白名單列表):
單個:path.repo: /mnt
多個:path.repo: [“/data” , “/mnt”]
2、在使用sshfs創建共享文件系統的時候,報錯read: Connection reset by peer
Es在災備的時候可以將數據存放到共享文件系統(一般選擇sshfs),或hdfs等。但是在執行如sudo sshfs -o allow_other root@192.168.10.11:/data/elasticsearch-repository /mnt的時候,報錯read:Connect reset by peer,剛開始以為是es的問題,最后發現就是ssh的問題。由于我使用的是阿里云服務器,并且使用秘鑰進行連接,我還以為是它的問題。最后:
ssh 192.168.10.11
ssh: connect to host 192.168.10.11 port 22: Connection refused
想起來我修改過ssh的端口,則需要將命令添加端口就好了,如下:
sudo sshfs -o allow_other root@192.168.10.11:/data/elasticsearch-repository /mnt -p 61822