zzxworld

使用阿里云 OSS 实现网站数据备份功能

线上运行的项目,无论大小,重要数据的备份是必须要考虑的事项。比如每天都在产生新数据的数据库。在不考虑「容灾」的前提下,通常可以选择定时复制要备份的数据并保存在项目所在的服务器上,不过使用云存储会是一个更加稳妥的选择。

为什么要云备份

关于容灾这个概念,通常指的是防范数据在一些极端情况下导致的不可逆的灾难性后果。以上面说的在项目服务器上保存备份数据为例,就存在一些大概率会导致备份数据丢失的风险。比如系统升级,或是对项目架构进行调整。在一些需要手动输入命令的场合一个误操作就会导致悲剧发生。

即便是不会发生误操作,在项目备份数据越来越大的时候,这些使用频率不高的备份数据也会无端占用宝贵的项目磁盘空间。而云存储的空间价格通常是要比服务器的磁盘价格便宜的,所以这也是一笔经济账。

云备份方案

我目前的服务器在阿里云,所以这里以阿里云 OSS 为例,先介绍一下我的备份思路和流程。

  1. 开通阿里云 OSS 服务。选择和自己云服务器同地区的 OSS 存储。
  2. 创建一个可以调用 OSS 服务的子帐号。
  3. 在项目服务器上配置好 OSS 帐号,然后通过自定义的备份脚本搭配 crontab 实现定时备份指定数据的功能。

前面两步很简单, 在阿里云后台就可以操作好,最重要的就是第三步。由于阿里云提供了一个可以操作 OSS 的辅助命令,所以最后这步也不是很难。

实现云存储备份

根据上面的方案,我们一步步来实现。

第一步进入阿里云 OSS 服务的界面,然后创建 Bucket。

create bucket on OSS

上面比较重要的选项有两个,分别是地域和存储类型。地域刚才说了, 一定要选择和自己服务器同一个地区的,这样备份数据时才能走内网地址,不会产生额外的流量费用。关于存储类型,越往后,存储费用越便宜。不过要注意最后两个归档类型,它们的费用是最低的,但使用前需要额外的解冻操作。如果没有长时间存储的特殊需求,就没必要选它们两个。我自己用的是「低频访问存储」。

第二步进入阿里云的 RAM 访问控制界面,创建一个用户,并添加访问管理 OSS 对象存储的权限。在这一步的认证管理项中,有一个 AccessKey 的功能,这是等下脚本访问 OSS 时要用到的令牌。完成用户的配置后,再次回到 OSS 的管理界面,进入刚创建的 Bucket,在 Bucket 授权策略中加入刚添加的用户帐号,并指定相应的授权资源。

最后一步。先通过下面的地址下载 OSS 的命令行工具。

我的服务器为 Linux,下载下来的文件名为 ossutil64。把这个下载的命令文件上传到服务器的 /usr/local/bin/ 目录下,并添加可执行权限。然后在服务器用户主目录下创建一个 .ossutilconfig 文件,文件内容如下:

[Credentials]
language=EN
accessKeyID=AccessKey
accessKeySecret=SecretKey
endpoint=oss-cn-hangzhou.aliyuncs.com

其中 accessKeyIDaccessKeySecret 就是第二步创建用户时可以拿到的。把后面的值替换为相应的内容。endpoint 是 Bucket 内网地址。

接下来就可以使用 ossutil64 命令了。比如复制一个文件到 OSS 上:

ossutil64 cp -f <local-file-path> oss://<bucket-name>/<file-path>

上面 <local file path> 代表本地文件路径,<bucket-name> 代表在 OSS 上创建的 Bucket 名称,<file-path> 是要在 OSS 上存放的文件路径。OSS 文件没有文件目录的概念,所以使用多级目录的地址时不用提前创建目录,这点和使用本地文件系统的方式相比,还是很方便的。

通过命令删除 OSS 上的文件也很方便,命令格式如下:

ossutil64 rm oss://<bucket-name>/<file-path>

以上命令都需要手动来执行,如果想要实现定时自动备份的功能,就需要借助 Linux 服务器上的 Crontab 工具了。类似于 Windows 上的计划任务。设置好排期,结合上面给出的 ossutil64 cp 命令示例,就可以实现定时把文件备份到 OSS 上的功能。

自定义备份命令

使用 ossutil64 默认提供的功能虽然已经可以达成备份目的了,不过我希望更进一步,实现按日期归档备份,并可以指定保留多长时间的备份。这需要自己写点 Shell 代码。

#!/bin/bash

FILENAME=`date +"%Y-%m-%d"`

function savefile {
    EXPIRED_FILENAME=`date --date="-$3 day" +"%Y-%m-%d"`
    SUFFIX=`echo $1|cut -d"." -f2`

    /usr/local/bin/ossutil64 cp -f $1 $2/${FILENAME}.$SUFFIX
    /usr/local/bin/ossutil64 rm $2/$EXPIRED_FILENAME.$SUFFIX
}

function syncfolder {
    ossutil64 sync $1 $2 -f
}

savefile /project1/database/database.sql oss://my-backup/project1/sql 2
savefile /project2/database/database.sql oss://my-backup/project2/sql 5

syncfolder /project3/uploads oss://my-backup/uploads

上面的脚本定义了两个函数,一个用来根据指定的时长来保留备份文件,一个用来同步目录。代码没几行,逻辑也不复杂,这里就不解释了。结合 Crontab,一个可定时备份,且支持自定义配置保留天数的备份功能达成。