2013年07月19日

穷人的服务器备份方案

作者 非鱼

长期以来公司都只有一台服务器,Web+Sql+Solr+File的物尽其用。但是一直以来让我睡不好的倒不是偶尔突发的性能问题,而是哪一天服务器的硬盘坏了怎么办?

服务器在机房里,看不到硬盘灯,只有三块硬盘做了RAID5,传说在SQL这种应用上,RAID5的寿命会降低不少,而公司所有的文件和数据都在这一台服务器上。万一哪天突然网站打不开了,跑到机房一看两块硬盘亮红灯,估计想死的心都有了。

终于,有了第二台服务器可以用,而且性能不弱,系统第一次启动起来,看到任务管理器里有24个CPU的时候,小小的激动了一下(双CPU双核六线程?),原来那台只有8个。

因为CPU多但是主频不高,内存大,所以决定把SQL数据库和文件存储移过来。移植过程还是比较简单的,基本上网站只断了10分钟不到一点。因为网站的附件存储是在MongoDB里以GridFS的方式存储的,所以省去了大概两个小时的拷文件的过程(大量的小文件复制起来是相当痛苦的,而且还容易损坏文件目录,千万几乎完全不可恢复)。

在实现了Web和数据的分离之后,剩下的问题就是怎么充分利用这两台分离的机器做好数据备份了。

第一步是MongoDB,修改原来的启动参数,加上–master,让它以主机身份启动。修改原来的Web服务器上的MongoDB,加上–slave –source=主机IP 的参数,让它以从机身份启动。这样新的文件和数据只要往主机的MongoDB里面插入,从机会自动去查询并同步过来,几乎实时(貌似5秒查询一次)。这样就完成了。

第二步是SQL Server,这个东西折腾了整整一个上午,午饭都没吃上,才搞定。先尝试使用复制的方式,新服务器设置为发布服务器,老的服务器设置为订阅服务器,通过发布服务器上的一个共享目录作为快照目录,订阅服务器定时去取并恢复数据到自身保持同步。基本上已经配置成功了,但是发现每次新数据库在定时生成快照的时候,网站就挂了,数据库处于不可读写的状态。不知道是我的问题还是微软的问题。而且在已经成功的一次快照生成以后,订阅服务器也一直没有把新数据同步过来。无奈关掉了这个功能。总不能每天到半夜才同步一次数据吧。

后来再尝试了镜像模式,在用户名的问题上查阅了N多资料,冒着被打屁股的风险重启了三四次数据库,终于搞定。主要是因为两台服务器之间没有域环境。具体的折腾过程就不说了,最终实现方法是在两台服务器上各新增一个同步的用户,密码相同,都设置为本机管理员,在服务里把sql server和sql agent两个服务的登录身份设成这两个用户,而不是默认的Local System。然后在两个Sql Server管理器里新增这个用户,注意是增加Windows登录验证的用户,而不是增加一个同名的sql server验证的用户(这是个低级错误,耽误了很长时间),并给这个新增的用户sysadmin的数据库身份,这样才可以远程登录。然后需要打开两个机器的5022端口互相可见。然后还有两个细节的设置,一个是RemoteDacEnabled,在sql管理器里服务器名字上点右键,点方面,右侧选中外围应用配置器,将这个属性的值改为True。另一个是给新增的用户以Connect的授权,不知道这个东西是怎么翻译的,反正管理界面里找不到。需要运行一个语句:GRANT CONNECT ON ENDPOINT::[服务器] TO [用户],不过要注意,这里的用户,是包含机器名前缀的用户名。而这里的服务器,并不是这台服务器本身的名字,这是最诡异的。

在执行这条语句之前,先到主服务器上,对数据库做完整备份,然后做一个日志备份,把备份复制到老的服务器上,还原到同一个数据库上,还原的时候注意选项选中norecovery的选项,还原完以后这个数据库会一直处于正在还原的状态。然后要同步的数据库上右键,镜像,配置安全性。选不使用见证服务器,主体服务器默认是当前服务器,没有问题,下面的端点名称可以随便写。然后下一步是镜像服务器示例,设定连接字符串,下面的端点名称也可以随便写,但是注意:这里的端点名称就是上面的那个SQL语句里的服务器名!再下一步账户名,留空即可。sql server会用它的进程启动所使用的那个用户名登录,就是前面新建的那个用户。再下一步,完成,开始镜像。正常的话,这里应该会弹出错误,说镜像服务器的5022端口无法连接之类的,因为你还没有执行前面的SQL授权语句。执行完后再回来点击开始镜像,如果看到下面的状态框里显示开始同步,数据库的状态也发生了变化,就成功了。如果还不行的话,在主机的hosts文件里添加镜像服务器的机器名的IP解析再试一下。完成后主服务器上的数据库会一直处于(主体,已同步)状态,而镜像服务器上的数据库会一直处于(镜像,已同步,正在还原)状态,镜像数据库是不可用的。

另外还有一个问题,如果sql server启用了使用AWE分配内存,那么以新建的用户名启动sql server的时候会出现这个用户名没有权限使用AWE的问题。需要进策略管理器,开始-运行-gpedit.msc,进windows安全设置里面的本地安全策略,找到允许内存页锁定的那个项,添加这个用户名进去,再重启sql server。

这样,最关键的两个数据,属于用户的数据,基本上处于两台机器完全同步的状态了,如果备用服务器挂了,没关系,主服务器完全不影响,只要把项目代码放上来,再搭建一个Web环境就可以了。再把备用服务器重装好以后,作为从服务器连接上来继续作为备份就好了。而如果主服务器挂了,两个备份数据库都可以通过简单的命令切换为主服务器来工作,立即接管整个数据处理工作。

剩下的就是文件的处理了,比如SVN的代码,Web文件的目录等,简单起见,安装了微软自家的SyncToy 2.1,这是个免费软件,很简单,添加源目录,目的目录,同步方式有三种:双向自动同步,单向数据保持同步,或单向只增不删的同步。而目的目录可以用映射的磁盘,也可以直接使用网络共享路径。每个同步任务可以定义一个名字,每次点击Run以后它会自动分析需要同步的文件,然后完成同步,最后可以查看同步失败的文件,同步了三个目录都出现了个别的失败的文件,小于万分之一,基本上是因为同步过程中文件发生了变化或者正在被写入锁定。这软件最大的好处,是可以无人干预的完成同步。通过建立计划任务,在该应用程序的后面加上参数 -R 方案名,它就可以自动完成同步过程。这样连项目文件也可以自动完成双机备份了。这样就可以现在就把Web环境配置好,必要时,只要换一下网线,改一下IP就可以完全切换过去了。

参考资料:SQL Server 2008 R2数据库镜像部署 http://liulike.blog.51cto.com/1355103/339183   这篇资料帮了大忙,只是用户名的问题没有提到,还是在国外的论坛上才找到的解决方案。