对网站维护者来说,可用性和数据安全非常重要。自发生了一些安全事件后,本站准备了几台备用服务器,以便在出现网络攻击、服务器故障时切换使用。之前多台服务器间数据库一直使用全量同步,今天忽然想到可以用Mysql主主同步/Redis主从复制备份网站,配置一次即可简单方便的切换服务器。
原来的方案
之前文章 WordPress备份方案和备份脚本 里给出了本人在多台服务器间备份的脚本,其核心思想是:
1. 网站程序和图片等文件使用rsync
在多台服务器间同步;
程序文件和数据库是最重要的数据,本人备份做法是:白天每小时备份一次,同步到备用服务器;每天凌晨备份一次,同步到次备用服务器;每星期备份一次,同步到备份服务器。通过不同地域和机房的三个备份,基本上确保了数据不会丢失,遇到问题时也能快速恢复网站。
这个方案看起来不错,就是恢复网站比较麻烦,基本上要经过这几步:
1. 切换域名DNS到新的服务器IP;这个比较简单,某些DNS支持宕机自动切换;
2. 因程序文件已经同步好,在备用服务器上直接取出备份数据,恢复数据即可让网站正常运行;
3. 主服务器恢复后,再把备用服务器上的数据同步到主服务器。
可以看到,方案中存在以下问题:
1. 可能存在数据丢失;数据不是实时备份的,恢复网站时的数据不是主服务器最新版本,会有少量数据丢失。当然对于个人WordPress网站而言,这个问题不大;
2. 恢复网站数据麻烦;备用服务器需要导入一次,等主服务器正常工作了,又要从备用服务器导出,然后再导入主服务器,不仅操作麻烦,还效率低下。
上周本站托管商家硬件升级花了几天才弄好,本人又重复了 “导出->导入->备用服务器恢复网站->导出->导入->切换到主服务器” 的过程,深感繁琐。
今天忽然意识到,完全可以使用Mysql主主复制(Mysql双主同步)以及Redis主从复制的方式来同步数据,从而避免上述的麻烦操作,并且保证数据不丢失。
新的备份方案
新的方案中,程序文件还是通过rsync在服务器间同步,但是Mysql数据和Redis数据的同步则通过主主复制/主从复制完成,既保证了数据完整性,还避免了手工操作。
接下来分别介绍Mysql双主同步和Redis主从复制设置。
Mysql主主复制(Mysql双主同步)
前文 mysql主从复制配置 介绍了Mysql主从复制的详细步骤,主主同步基本上差不多,只是在从服务器上多了一遍配置而已。
本文以Mariadb 10.4版本为例介绍Mysql主主同步配置,其操作流程如下:
1. 在第一个主服务器(master)上,配置同步用的server_id、binlog等:编辑 /etc/my.cnf.d/server.cnf
文件,server 段加入如下内容:
[server] server-id = 1 log-bin = /var/lib/mysql/mysql-bin.log binlog-do-db = tlanyan # 如果有多个数据库要复制,写多行 replicate-do-db = tlanyan # 如果有多个数据库要复制,写多行 expire_logs_days = 15 relay-log = /var/lib/mysql/mysql-relay-bin.log auto-increment-increment = 2 auto-increment-offset = 1
一些教程里用的server_id、log_bin等字段,正常来说Mariadb/Mysql都支持横杆和下划线两种风格,写法都没问题
请务必设置auto-increment-increment和auto-increment-offset两个参数,否则可能会出现”Error ‘Duplicate entry xxx for key ‘PRIMARY” on query.“的错误,导致复制中断
然后重启Mariadb服务器:systemctl restart mariadb
2. 在Mysql中创建复制账号,并赋予复制权限:
mysql # 该命令进入数据库 # 创建复制数据库账号,把replica-username和password替换成具体的用户名和密码 create user 'replica-username'@'%' identified by 'password'; # 赋予复制权限 grant replication slave on *.* to 'replica-username'@'%'; flush privileges;
3. 导出数据,并记录当前数据库状态。可以使用Mysql自带的mysqldump
工具导出:
mysqldump tlanyan | gzip > tlanyan-20201103.sql.gz
如果你想导出时保证数据一致性,有两种做法:第一是锁表:
use tlanyan;
# 设置表为只读状态
FLUSH TABLES WITH READ LOCK;
# 接着mysqldump数据
# 解锁表
UNLOCK TABLES;
第二种是导出时使用--single-transaction
选项,导出数据库的当前快照:
mysqldump --single-transaction tlanyan | gzip > tlanyan-20201103.sql.gz
对于个人WordPress网站,除文章外的其他数据不重要,因此本人操作时未使用这两种方式。
导出数据后,在Mysql中查看二进制日志的状态:show master status
,其输出如下(如果用了锁表方式,建议在解锁前执行):
+------------------+----------+----------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +------------------+----------+----------------+------------------+ | mysql-bin.000001 | 233 | tlanyan | | +------------------+----------+----------------+------------------+
请记住 File 和 Position 的值,配置从库时会用到。
4. 将导出的数据库文件复制到第二个主服务器并导入(需要先创建好同名数据库):
mysql tlanyan < tlanyan-20201103.sql
5. 配置第二个主服务器的server_id等信息:编辑 /etc/my.cnf.d/server.cnf
文件,server 段加入如下内容:
[server] server-id = 2 # 必须和第一个主服务器不同 log-bin = /var/lib/mysql/mysql-bin.log binlog-do-db = tlanyan # 如果有多个数据库要复制,写多行 replicate-do-db = tlanyan # 如果有多个数据库要复制,写多行 expire_logs_days = 15 relay-log = /var/lib/mysql/mysql-relay-bin.log auto-increment-increment = 2 auto-increment-offset = 2
然后重启Mariadb服务器:systemctl restart mariadb
6. 配置第二个主服务器从第一个主服务复制数据:
# 进入mysql # 配置同步第一个主服务器的数据,ip、username、password、mysql-bin.000001和233都改成自己的 change master to master_host='ip', master_user='username', master_password='password', master_log_file='mysql-bin.000001', master_log_pos=233; # 启动复制进程 start slave
在Mysql中,通过show slave status\G;
命令可以查看复制状态,有类似如下输出:
Slave_IO_State: Waiting for master to send event Master_Host: xxxx Master_User: xxxx Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000001 Read_Master_Log_Pos: 571947 Relay_Log_File: mysql-relay-bin.000002 Relay_Log_Pos: 569756 Relay_Master_Log_File: mysql-bin.000001 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: tlanyan // 略去一些中间行 Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it Slave_DDL_Groups: 2 Slave_Non_Transactional_Groups: 1356 Slave_Transactional_Groups: 4308
上述过程配置好了主从复制,主主复制还需要做如下操作:
- 在第二个主服务器上创建第一个服务器同步用的账号密码,并赋予权限,请参考第2步;
- 在第二个主服务器上执行
show master status
,记住File和Position的值,请参考第3步; - 在第一个服务器上配置同步第二个服务器,请参考第6步。
经过上述操作,Mysql双主同步/Mysql主主复制便完成了。在任何一个服务器上创建新的表,插入数据,其他服务器上很快便能看到,说明我们的配置已经成功。
另外需要注意的是,如果服务器有防火墙/安全组,请记得放行。
Redis主从复制
如果你的程序还用到了Redis,那么还需要配置Redis数据的同步。可惜的是,Redis官方只支持主从复制,不支持主主同步。
Redis主从复制配置很简单,基本上只需要在从服务器上配置即可。操作为:
1. 编辑主服务器的/etc/redis.conf
文件,将 bind 12.0.0.1
改成 bind 0.0.0.0
,然后重启Redis:systemctl restart redis
;
2. 编辑从服务器的 /etc/redis.conf
文件,找到 replicaof 指令,改成
replicaof 主服务器ip 6379 # 6379是默认Redis端口,如果修改过请记得保持一致
Redis默认从服务器只读,不能写入数据。在本人情形中,切换到备用服务器时需要可写,因此要设置replica-read-only
:
replica-read-only yes
配置好后重启Redis:systemctl restart redis
。
因为Black lives masters的影响,slave这个词在不少软件中被替换(例如Leader-follower)。网上许多教程用的旧版Redis,配置中的slaveof即本文中的replicaof
接着通过 redis-cli info keyspace
命令便可以看到数据已经与主服务器一致。
需要注意的是,如果主服务器有防火墙/安全组,请记得放行。
注意事项
经过上述设置,数据库中的数据会自动同步到备用服务器,恢复网站时终于不用再导入/导出数据文件了。但还有一些注意事项:
- Mysql主主同步/Redis复制对数据做的更改即时生效,如果数据出现意外,从库的数据立马受到影响,因此建议还是要用全量备份或者增量备份+binlog的方式确保数据安全;
- 千万要设置好防火墙,不要将无密码的Redis端口暴露在公网上,否则会有严重的安全风险;
- Redis的数据默认会同步到
/var/lib/redis
目录的dump.rdb
文件中,使用其可以恢复Redis。
求博主分享wp+woo优化教程🙏
没用过woo,不过应该和通用优化差不多,本站搜一下wordpress性能优化
感谢分享