本文介紹了如何利用OOS實現對Redis實例的定時備份并自動轉儲到OSS,以解決數據安全、運維復雜度和成本等問題。
前提條件
已開通函數計算服務,詳情請參見快速創建函數。
功能背景
隨著企業業務數據的快速增長,Redis作為高性能的內存數據存儲方案,在多種應用場景下承擔著重要的角色。為確保數據安全,定時備份成為了不可或缺的一環。Redis實例定時備份是關鍵數據庫管理任務的一個重要組成部分,它主要服務于數據的災難恢復、歷史數據查詢、環境克隆等應用場景。然而,在目前的自動或手動備份中,雖然支持定時備份功能,可以根據用戶的業務需求,設置備份周期進行自動備份。但此方式存在以下不足:
數據安全風險:在實例刪除后,傳統的定時備份無法保留備份數據,導致數據不能永久保存,存在數據丟失的風險。
運維工作繁瑣:缺少自動化的備份轉儲機制,需要手動操作備份過程,包括下載和上傳至云存儲服務,這一流程不僅耗時,同時也容易出錯。
運維成本增加:由于備份流程需要人工介入,過程中容易出錯,需要額外的時間和資源投入,從而增加了整體的運維成本。
效率較低:在沒有集中管理的備份方案前,為多個實例或跨地域實例執行備份時,效率相對偏低,管理復雜度高。
監控及告警能力不足:缺乏有效的監控和告警機制,使得備份任務的執行狀態難以實時掌握,一旦出現失敗或異常問題,及時響應和處理的能力受限。
針對上述不足,結合OOS的編排能力,OOS推出了定時備份Redis實例并自動轉儲至OSS的功能,為用戶提供了一個高效、安全且自動化的備份解決方案。此方案有以下優勢:
數據安全性提高:通過自動上傳備份文件至OSS, 利用OSS的數據冗余存儲機制, 確保硬件失效時的數據持久性和可用性;此外,及時Redis實例刪除也能永久保存。
完全自動化:一旦配置完成,備份文件將自動、定時上傳到OSS,無需人工干預,大大減輕了運維負擔,降低了操作錯誤。
多實例多地域集中管理:OOS定時備份Redis任務支持一次選擇多個實例。此外,OOS支持跨區域轉儲OSS,您可以將多個地域的Redis實例統一備份到同一OSS存儲桶中。
靈活的備份策略和成本控制:用戶可以根據自己的需要設置備份頻率,通過OSS的生命周期管理策略,自動清理過期的備份文件,從而更有效地控制成本。
監控和告警:結合OSS和云監控,用戶可以實時監控備份狀態,一旦備份失敗或有其他問題,可以及時收到告警,確保數據的安全性。
操作步驟
此功能使用過程中可能會產生部分費用,計費詳情參考Redis備份費用說明和函數計算費用說明
登錄OOS控制臺。
在左側導航欄找到
,單擊創建。設置定時規則。
這里定時類型有“立即執行、僅在指定時間執行一次、周期性重復執行”三種方式。其中“立即執行”會在創建任務后立即進行重啟操作,“僅在指定時間執行一次”只會在您設定的某個時間點執行一次,“周期性重復執行”則會安裝一定的規則重復執行,如每一小時執行一次。
這里我們選擇周期性重復執行,可以通過快速選擇設置重復的頻率,熟悉Cron表達式的同學也可以通過Cron表達式進行設置。本教程通過快速選擇設置重復的頻率,設置每小時執行一次,之后單擊確定。
搜索模板ACS-Redis-BulkyCreateBackupAndUploadToOSS,然后進行勾選。
接下來選擇要進行備份的實例,首先選擇實例所在地域,然后選擇目標實例,單擊確定。
選擇要轉儲的OSS存儲桶。
配置執行任務所需的RAM角色:
創建OOS編排OpenAPI角色,可參考為OOS服務設置RAM權限配置 OOS 所需的 RAM 角色并授權,權限策略如下:
{ "Version": "1", "Statement": [ { "Action": [ "kvstore:CreateBackup", "kvstore:DescribeBackupTasks", "kvstore:DescribeBackups", "kvstore:DescribeInstances" ], "Resource": "*", "Effect": "Allow" }, { "Action": [ "ros:CreateStack", "ros:DeleteStack", "ros:GetStack" ], "Resource": "*", "Effect": "Allow" }, { "Action": "oos:StartExecution", "Resource": "*", "Effect": "Allow" }, { "Action": [ "fc:CreateFunction", "fc:CreateService", "fc:DeleteFunction", "fc:DeleteService", "fc:GetFunction", "fc:GetService", "fc:InvokeFunction" ], "Resource": "*", "Effect": "Allow" }, { "Condition": { "StringEquals": { "acs:Service": "fc.aliyuncs.com" } }, "Action": "ram:PassRole", "Resource": "*", "Effect": "Allow" } ] }
創建一個通過函數計算下載備份文件所需要的角色,可點擊角色快捷創建配置 FC 所需的 RAM 角色(AliyunFCDefaultRole)進行快速創建。
點擊“創建”->“確定”,定時備份轉儲到OSS的任務就創建完成了
查看任務執行結果
a. 您可以等到到達您設定的觸發時間來查看備份結果
b. 點擊“立即觸發”來執行備份轉儲任務查看結果
此時任務會進入運行中,可通過執行日志查看任務執行進度
查看轉儲至 OSS 中的備份文件
等待執行狀態變成“已結束”,可以點擊執行ID
點擊子執行ID
查看輸出
此時登錄此輸出的地址就可以查看轉存到OSS的備份文件了
備份文件存儲目錄格式為:
Backup_[實例 ID]/[日期 (格式為 YYYY-MM-DD)]/[OOS備份任務ID]/[備份文件名稱].rdb
如果實例為非集群架構,則每次備份將產生 1 個 rdb 文件
如果實例為集群架構,由于每個分片將會獨立備份,因此每次備份將產生與分片數量一致的 rdb 文件(例如 8 分片集群則每次產生 8 個 rdb 文件)
轉儲至 OOS 中的備份不再有自動清理時間,可根據需要保留或刪除
附錄
執行流程圖
整體執行流程圖:
其中創建redis備份并上傳到OSS流程:
模板
上述步驟中使用的模板“ACS-Redis-BulkyCreateBackupAndUploadToOSS”內容如下(模板鏈接):
FormatVersion: OOS-2019-06-01
Description:
en: Create Redis backups in batches and upload them to OSS. Backing up redis and using fc to upload the backup to OSS may incur charges. For billing details, please refer to <a href='https://help .aliyun.com/zh/redis/user-guide/automatic-or-manual-backup#e606eb29c7mew'>Redis Backup Fee Instructions</a> and <a href='http://bestwisewords.com/zh/ fc/product-overview/billing-overview'>Function calculation billing instructions</a>
zh-cn: 批量創建Redis備份并上傳到OSS。備份redis和使用fc將備份上傳到oss都可能會產生費用,計費詳情參考<a href='http://bestwisewords.com/zh/redis/user-guide/automatic-or-manual-backup#e606eb29c7mew'>Redis備份費用說明</a>和<a href='http://bestwisewords.com/zh/fc/product-overview/billing-overview'>函數計算計費說明</a>
name-en: ACS-Redis-BulkyCreateBackupAndUploadToOSS
name-zh-cn: 批量創建Redis備份并上傳到OSS
Parameters:
regionId:
Label:
en: RegionId
zh-cn: 地域ID
Type: String
AssociationProperty: RegionId
Default: '{{ACS::RegionId}}'
targets:
Type: Json
Label:
en: TargetInstance
zh-cn: 目標實例
AssociationProperty: Targets
AssociationPropertyMetadata:
ResourceType: ALIYUN::Redis::Instance
RegionId: regionId
OSSRegionId:
Label:
en: OSSRegionId
zh-cn: OSS Bucket所在地域ID
Type: String
AssociationProperty: RegionId
OSSBucketName:
Label:
en: OSSBucketName
zh-cn: OSS Bucket名稱
Type: String
AssociationProperty: ALIYUN::OSS::Bucket::BucketName
AssociationPropertyMetadata:
RegionId: ${OSSRegionId}
rateControl:
Label:
en: RateControl
zh-cn: 任務執行的并發比率
Type: Json
AssociationProperty: RateControl
Default:
Mode: Concurrency
MaxErrors: 0
Concurrency: 10
OOSAssumeRole:
Label:
en: OOSAssumeRole
zh-cn: OOS扮演的RAM角色
Type: String
Default: ''
RamRole: '{{ OOSAssumeRole }}'
Tasks:
- Name: GetInstance
Description:
en: Get the redis instances
zh-cn: 獲取Redis實例
Action: ACS::SelectTargets
Properties:
ResourceType: ALIYUN::Redis::Instance
RegionId: '{{ regionId }}'
Filters:
- '{{ targets }}'
Outputs:
InstanceIds:
Type: List
ValueSelector: Instances.Instance[].InstanceId
- Name: CreateBackupAndUploadToOSS
Action: ACS::Redis::CreateBackupAndUploadToOSS
Description:
en: Create backup and upload to OSS
zh-cn: 創建Redis備份并上傳到OSS
Properties:
regionId: '{{ regionId }}'
instanceId: '{{ ACS::TaskLoopItem }}'
OSSRegionId: '{{ OSSRegionId }}'
OSSBucketName: '{{ OSSBucketName }}'
Loop:
RateControl: '{{ rateControl }}'
Items: '{{ GetInstance.InstanceIds }}'
Outputs:
OSSObjectURLs:
AggregateType: Fn::ListJoin
AggregateField: OSSObjectURL
Outputs:
OSSObjectURL:
Type: String
ValueSelector: .OSSObjectURL + "{{ACS::ExecutionId}}/" | split(".t0") | .[0]
Outputs:
OSSObjectURLs:
Type: List
Value: '{{ CreateBackupAndUploadToOSS.OSSObjectURLs }}'
其中Action: ACS::Redis::CreateBackupAndUploadToOSS內容如下:
FormatVersion: OOS-2019-06-01
Description:
en: Create redis backup and upload to OSS
zh-cn: 創建Redis備份并上傳到OSS
name-en: ACS::Redis::CreateBackupAndUploadToOSS
name-zh-cn: 創建Redis備份并上傳到OSS
Parameters:
regionId:
Label:
en: RegionId
zh-cn: 地域ID
Type: String
AssociationProperty: RegionId
instanceId:
Label:
en: InstanceId
zh-cn: 實例ID
Type: String
AssociationProperty: ALIYUN::Redis::Instance::InstanceId
AssociationPropertyMetadata:
RegionId: ${regionId}
OSSRegionId:
Label:
en: OSSRegionId
zh-cn: OSS bucket所在地域ID
Type: String
AssociationProperty: RegionId
OSSBucketName:
Label:
en: OSSBucketName
zh-cn: OSS Bucket 名稱
Type: String
AssociationProperty: ALIYUN::OSS::Bucket::BucketName
AssociationPropertyMetadata:
RegionId: ${OSSRegionId}
Default: ''
Tasks:
- Name: CreateBackup
Action: ACS::ExecuteApi
Description:
en: Create backup
zh-cn: 創建Redis備份
Properties:
Service: r-kvstore
API: CreateBackup
Parameters:
RegionId: '{{ regionId }}'
InstanceId: '{{ instanceId }}'
Outputs:
BackupJobID:
Type: String
ValueSelector: .BackupJobID
- Name: WaitForBackupCreated
Action: ACS::WaitFor
Description:
en: Wait for backup created
zh-cn: 等待備份創建完成
Retries: 30
DelayType: Exponential
Delay: 2
BackOff: 2
Properties:
Service: r-kvstore
API: DescribeBackupTasks
Parameters:
RegionId: '{{ regionId }}'
InstanceId: '{{ instanceId }}'
BackupJobId: '{{ CreateBackup.BackupJobID }}'
DesiredValues:
- Finished
NotDesiredValues: []
StopRetryValues: []
PropertySelector: .BackupJobs[].BackupProgressStatus
- Name: GetBackupDownloadUrl
Action: ACS::ExecuteApi
Description:
en: Get backup download url
zh-cn: 獲取備份下載地址
Properties:
Service: r-kvstore
API: DescribeBackups
Parameters:
RegionId: '{{ regionId }}'
InstanceId: '{{ instanceId }}'
BackupJobId: '{{ CreateBackup.BackupJobID }}'
StartTime:
Fn::FormatUTCTime:
- Fn::AddHour:
- '{{ ACS::CurrentUTCTime }}'
- -1
- '%Y-%m-%dT%H:%MZ'
EndTime:
Fn::FormatUTCTime:
- '{{ ACS::CurrentUTCTime }}'
- '%Y-%m-%dT%H:%MZ'
Outputs:
BackupDownloadURL:
Type: List
ValueSelector: .Backups.Backup[].BackupDownloadURL
- Name: UploadBackupToOSS
Action: ACS::FC::ExecuteScript
Description:
en: Upload backup to OSS
zh-cn: 上傳備份到OSS
Properties:
runtime: python3.10
handler: index.handler
role: acs:ram::{{ACS::AccountId}}:role/AliyunFcDefaultRole
script: |-
import oss2
import requests
def handler(event, context):
auth = oss2.StsAuth(context.credentials.access_key_id, context.credentials.access_key_secret, context.credentials.security_token)
endpoint = 'https://oss-{{OSSRegionId}}.aliyuncs.com'
bucket = oss2.Bucket(auth, endpoint, '{{OSSBucketName}}')
unique_identifier = '{{ACS::TaskLoopItem}}'.split('?')[0].split('/')[-1]
execution_id = '{{ACS::ExecutionId}}'.split('.')[0]
input = requests.get('{{ACS::TaskLoopItem}}')
bucket.put_object(f'Backup_{{InstanceId}}/{{ACS::CurrentDate}}/{execution_id}/{unique_identifier}', input)
Loop:
Items: '{{ GetBackupDownloadUrl.BackupDownloadURL }}'
RateControl:
Mode: Concurrency
MaxErrors: 0
Concurrency: 20
Outputs:
OSSObjectURL:
Type: String
Value: https://oss.console.aliyun.com/bucket/oss-{{OSSRegionId}}/{{OSSBucketName}}/object?path=Backup_{{InstanceId}}/{{ACS::CurrentDate}}/