这小节我们要讨论应用程序管理的另一个方面:生产服务器上数据的备份和恢复。我们经常会遇到生产服务器的网络断了、硬盘坏了、操作系统崩溃、或者数据库不可用了等各种异常情况,所以维护人员需要对生产服务器上的应用和数据做好异地灾备,冷备热备的准备。在接下来的介绍中,讲解了如何备份应用、如何备份/恢复Mysql数据库和redis数据库。
## [](https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/12.4.md#应用备份)应用备份
在大多数集群环境下,Web应用程序基本不需要备份,因为这个其实就是一个代码副本,我们在本地开发环境中,或者版本控制系统中已经保持这些代码。但是很多时候,一些开发的站点需要用户来上传文件,那么我们需要对这些用户上传的文件进行备份。目前其实有一种合适的做法就是把和网站相关的需要存储的文件存储到云储存,这样即使系统崩溃,只要我们的文件还在云存储上,至少数据不会丢失。
如果我们没有采用云储存的情况下,如何做到网站的备份呢?这里我们介绍一个文件同步工具rsync:rsync能够实现网站的备份,不同系统的文件的同步,如果是windows的话,需要windows版本cwrsync。
### [](https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/12.4.md#rsync安装)rsync安装
rysnc的官方网站:[http://rsync.samba.org/](http://rsync.samba.org/) 可以从上面获取最新版本的源码。当然,因为rsync是一款非常有用的软件,所以很多Linux的发行版本都将它收录在内了。
软件包安装
~~~
# sudo apt-get install rsync 注:在debian、ubuntu 等在线安装方法;
# yum install rsync 注:Fedora、Redhat、CentOS 等在线安装方法;
# rpm -ivh rsync 注:Fedora、Redhat、CentOS 等rpm包安装方法;
~~~
其它Linux发行版,请用相应的软件包管理方法来安装。源码包安装
~~~
tar xvf rsync-xxx.tar.gz
cd rsync-xxx
./configure --prefix=/usr ;make ;make install 注:在用源码包编译安装之前,您得安装gcc等编译工具才行;
~~~
### [](https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/12.4.md#rsync配置)rsync配置
rsync主要有以下三个配置文件rsyncd.conf(主配置文件)、rsyncd.secrets(密码文件)、rsyncd.motd(rysnc服务器信息)。
关于这几个文件的配置大家可以参考官方网站或者其他介绍rsync的网站,下面介绍服务器端和客户端如何开启
* 服务端开启:
~~~
#/usr/bin/rsync --daemon --config=/etc/rsyncd.conf
~~~
--daemon参数方式,是让rsync以服务器模式运行。把rsync加入开机启动
~~~
echo 'rsync --daemon' >> /etc/rc.d/rc.local
~~~
设置rsync密码
~~~
echo '你的用户名:你的密码' > /etc/rsyncd.secrets
chmod 600 /etc/rsyncd.secrets
~~~
* 客户端同步:
客户端可以通过如下命令同步服务器上的文件:
~~~
rsync -avzP --delete --password-file=rsyncd.secrets 用户名@192.168.145.5::www /var/rsync/backup
~~~
这条命令,简要的说明一下几个要点:
1. -avzP是啥,读者可以使用--help查看
2. --delete 是为了比如A上删除了一个文件,同步的时候,B会自动删除相对应的文件
3. --password-file 客户端中/etc/rsyncd.secrets设置的密码,要和服务端的 /etc/rsyncd.secrets 中的密码一样,这样cron运行的时候,就不需要密码了
4. 这条命令中的"用户名"为服务端的 /etc/rsyncd.secrets中的用户名
5. 这条命令中的 192.168.145.5 为服务端的IP地址
6. ::www,注意是2个 : 号,www为服务端的配置文件 /etc/rsyncd.conf 中的[www],意思是根据服务端上的/etc/rsyncd.conf来同步其中的[www]段内容,一个 : 号的时候,用于不根据配置文件,直接同步指定目录。
为了让同步实时性,可以设置crontab,保持rsync每分钟同步,当然用户也可以根据文件的重要程度设置不同的同步频率。
## [](https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/12.4.md#mysql备份)MySQL备份
应用数据库目前还是MySQL为主流,目前MySQL的备份有两种方式:热备份和冷备份,热备份目前主要是采用master/slave方式(master/slave方式的同步目前主要用于数据库读写分离,也可以用于热备份数据),关于如何配置这方面的资料,大家可以找到很多。冷备份的话就是数据有一定的延迟,但是可以保证该时间段之前的数据完整,例如有些时候可能我们的误操作引起了数据的丢失,那么master/slave模式是无法找回丢失数据的,但是通过冷备份可以部分恢复数据。
冷备份一般使用shell脚本来实现定时备份数据库,然后通过上面介绍rsync同步非本地机房的一台服务器。
下面这个是定时备份mysql的备份脚本,我们使用了mysqldump程序,这个命令可以把数据库导出到一个文件中。
~~~
#!/bin/bash
# 以下配置信息请自己修改
mysql_user="USER" #MySQL备份用户
mysql_password="PASSWORD" #MySQL备份用户的密码
mysql_host="localhost"
mysql_port="3306"
mysql_charset="utf8" #MySQL编码
backup_db_arr=("db1" "db2") #要备份的数据库名称,多个用空格分开隔开 如("db1" "db2" "db3")
backup_location=/var/www/mysql #备份数据存放位置,末尾请不要带"/",此项可以保持默认,程序会自动创建文件夹
expire_backup_delete="ON" #是否开启过期备份删除 ON为开启 OFF为关闭
expire_days=3 #过期时间天数 默认为三天,此项只有在expire_backup_delete开启时有效
# 本行开始以下不需要修改
backup_time=`date +%Y%m%d%H%M` #定义备份详细时间
backup_Ymd=`date +%Y-%m-%d` #定义备份目录中的年月日时间
backup_3ago=`date -d '3 days ago' +%Y-%m-%d` #3天之前的日期
backup_dir=$backup_location/$backup_Ymd #备份文件夹全路径
welcome_msg="Welcome to use MySQL backup tools!" #欢迎语
# 判断MYSQL是否启动,mysql没有启动则备份退出
mysql_ps=`ps -ef |grep mysql |wc -l`
mysql_listen=`netstat -an |grep LISTEN |grep $mysql_port|wc -l`
if [ [$mysql_ps == 0] -o [$mysql_listen == 0] ]; then
echo "ERROR:MySQL is not running! backup stop!"
exit
else
echo $welcome_msg
fi
# 连接到mysql数据库,无法连接则备份退出
mysql -h$mysql_host -P$mysql_port -u$mysql_user -p$mysql_password <<end
use mysql;
select host,user from user where user='root' and host='localhost';
exit
end
flag=`echo $?`
if [ $flag != "0" ]; then
echo "ERROR:Can't connect mysql server! backup stop!"
exit
else
echo "MySQL connect ok! Please wait......"
# 判断有没有定义备份的数据库,如果定义则开始备份,否则退出备份
if [ "$backup_db_arr" != "" ];then
#dbnames=$(cut -d ',' -f1-5 $backup_database)
#echo "arr is (${backup_db_arr[@]})"
for dbname in ${backup_db_arr[@]}
do
echo "database $dbname backup start..."
`mkdir -p $backup_dir`
`mysqldump -h$mysql_host -P$mysql_port -u$mysql_user -p$mysql_password $dbname --default-character-set=$mysql_charset | gzip > $backup_dir/$dbname-$backup_time.sql.gz`
flag=`echo $?`
if [ $flag == "0" ];then
echo "database $dbname success backup to $backup_dir/$dbname-$backup_time.sql.gz"
else
echo "database $dbname backup fail!"
fi
done
else
echo "ERROR:No database to backup! backup stop"
exit
fi
# 如果开启了删除过期备份,则进行删除操作
if [ "$expire_backup_delete" == "ON" -a "$backup_location" != "" ];then
#`find $backup_location/ -type d -o -type f -ctime +$expire_days -exec rm -rf {} \;`
`find $backup_location/ -type d -mtime +$expire_days | xargs rm -rf`
echo "Expired backup data delete complete!"
fi
echo "All database backup success! Thank you!"
exit
fi
~~~
修改shell脚本的属性:
~~~
chmod 600 /root/mysql_backup.sh
chmod +x /root/mysql_backup.sh
~~~
设置好属性之后,把命令加入crontab,我们设置了每天00:00定时自动备份,然后把备份的脚本目录/var/www/mysql设置为rsync同步目录。
~~~
00 00 * * * /root/mysql_backup.sh
~~~
## [](https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/12.4.md#mysql恢复)MySQL恢复
前面介绍MySQL备份分为热备份和冷备份,热备份主要的目的是为了能够实时的恢复,例如应用服务器出现了硬盘故障,那么我们可以通过修改配置文件把数据库的读取和写入改成slave,这样就可以尽量少时间的中断服务。
但是有时候我们需要通过冷备份的SQL来进行数据恢复,既然有了数据库的备份,就可以通过命令导入:
~~~
mysql -u username -p databse < backup.sql
~~~
可以看到,导出和导入数据库数据都是相当简单,不过如果还需要管理权限,或者其他的一些字符集的设置的话,可能会稍微复杂一些,但是这些都是可以通过一些命令来完成的。
## [](https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/12.4.md#redis备份)redis备份
redis是目前我们使用最多的NoSQL,它的备份也分为两种:热备份和冷备份,redis也支持master/slave模式,所以我们的热备份可以通过这种方式实现,相应的配置大家可以参考官方的文档配置,相当的简单。我们这里介绍冷备份的方式:redis其实会定时的把内存里面的缓存数据保存到数据库文件里面,我们备份只要备份相应的文件就可以,就是利用前面介绍的rsync备份到非本地机房就可以实现。
## [](https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/12.4.md#redis恢复)redis恢复
redis的恢复分为热备份恢复和冷备份恢复,热备份恢复的目的和方法同MySQL的恢复一样,只要修改应用的相应的数据库连接即可。
但是有时候我们需要根据冷备份来恢复数据,redis的冷备份恢复其实就是只要把保存的数据库文件copy到redis的工作目录,然后启动redis就可以了,redis在启动的时候会自动加载数据库文件到内存中,启动的速度根据数据库的文件大小来决定。
## [](https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/12.4.md#小结)小结
本小节介绍了我们的应用部分的备份和恢复,即如何做好灾备,包括文件的备份、数据库的备份。同时也介绍了使用rsync同步不同系统的文件,MySQL数据库和redis数据库的备份和恢复,希望通过本小节的介绍,能够给作为开发的你对于线上产品的灾备方案提供一个参考方案。
- 第一章 Go环境配置
- 1.1 Go安装
- 1.2 GOPATH 与工作空间
- 1.3 Go 命令
- 1.4 Go开发工具
- 1.5 小结
- 第二章 Go语言基础
- 2.1 你好,Go
- 2.2 Go基础
- 2.3 流程和函数
- 2.4 struct类型
- 2.5 面向对象
- 2.6 interface
- 2.7 并发
- 2.8 总结
- 第三章 Web基础
- 3.1 Web工作方式
- 3.2 Go搭建一个Web服务器
- 3.3 Go如何使得Web工作
- 3.4 Go的http包详解
- 3.5 小结
- 第四章 表单
- 4.1 处理表单的输入
- 4.2 验证表单的输入
- 4.3 预防跨站脚本
- 4.4 防止多次递交表单
- 4.5 处理文件上传
- 4.6 小结
- 第五章 访问数据库
- 5.1 database/sql接口
- 5.2 使用MySQL数据库
- 5.3 使用SQLite数据库
- 5.4 使用PostgreSQL数据库
- 5.5 使用beedb库进行ORM开发
- 5.6 NOSQL数据库操作
- 5.7 小结
- 第六章 session和数据存储
- 6.1 session和cookie
- 6.2 Go如何使用session
- 6.3 session存储
- 6.4 预防session劫持
- 6.5 小结
- 第七章 文本处理
- 7.1 XML处理
- 7.2 JSON处理
- 7.3 正则处理
- 7.4 模板处理
- 7.5 文件操作
- 7.6 字符串处理
- 7.7 小结
- 第八章 Web服务
- 8.1 Socket编程
- 8.2 WebSocket
- 8.3 REST
- 8.4 RPC
- 8.5 小结
- 第九章 安全与加密
- 9.1 预防CSRF攻击
- 9.2 确保输入过滤
- 9.3 避免XSS攻击
- 9.4 避免SQL注入
- 9.5 存储密码
- 9.6 加密和解密数据
- 9.7 小结
- 第十章 国际化和本地化
- 10.1 设置默认地区
- 10.2 本地化资源
- 10.3 国际化站点
- 10.4 小结
- 第十一章 错误处理,调试和测试
- 11.1 错误处理
- 11.2 使用GDB调试
- 11.3 Go怎么写测试用例
- 11.4 小结
- 第十二章 部署与维护
- 12.1 应用日志
- 12.2 网站错误处理
- 12.3 应用部署
- 12.4 备份和恢复
- 12.5 小结
- 第十三章 如何设计一个Web框架
- 13.1 项目规划
- 13.2 自定义路由器设计
- 13.3 controller设计
- 13.4 日志和配置设计
- 13.5 实现博客的增删改
- 13.6 小结
- 第十四章 扩展Web框架
- 14.1 静态文件支持
- 14.2 Session支持
- 14.3 表单及验证支持
- 14.4 用户认证
- 14.5 多语言支持
- 14.6 pprof支持
- 14.7 小结
- 附录A 参考资料