家庭数据中心系列 wordpress多节点”半自动”、”近乎”实时同步方案

项目背景

我这几天一直在思考如何"白嫖cloudflare free计划的tunnel实现多节点wordpress就近访问及容灾解决方案",但是要实现这个解决方案有个大前提:这些节点wordpress站点内容是一样的,换句话说,要求多节点wordpress的数据是同步的。

回头看现在我的多个节点wordpress的数据同步方案,还是依靠主wordpress站点的WPvivid backup插件定期生成整个wordpress(程序文件+数据库)的完整备份,然后通过syncthing实时同步到其他wordpress站点的WPvivid backup插件的位置,最后需要的时候通过人工以”一键恢复”的方式同步。。。太low了有没有?而且我也并没有定时恢复的计划~(主要是懒,而且要看当时的心情)。

总而言之,这种简陋的同步方案已经不符合我现在的身份场景了,急需升级改造。

数据库同步方案思考

由于有syncthing作为我现在的底层支撑技术之一,wordpress程序数据本身的同步已经不是问题了,关键在于多节点wordpress对应的数据库内容同步应该采用何种解决方案,一般来说,有3钟方式可选:
1、直接采用同一个mariadb数据库

如果多站点仅仅是冗余的作用:默认博客的访问请求只访问主站点,主站点故障才切换备用站点,备用站点故障才切换到容灾站点,那采用一个数据库也没有问题,因为同时只有一个wordpress站点在读写。但是这种情况一旦唯一的一个数据库出现问题就全崩了,并且如果我的家庭数据中心本身断网、断电,数据库也没了,单纯容灾站点一个wordpress,没有数据库也没用,所以直接pass。
2、采用数据库主从同步

考虑到wordpress主站点、备份站点都在家庭数据中心中,所以可以考虑主、备份wordpress站点都连家庭数据中心内同一个mariadb数据库,容灾站点单独运行一个mariadb数据库,家庭数据中心的mariadb为主、容灾站点的mariadb为从,配置主从同步,这样是肯定没有问题的(tailscale作为底层支撑技术之一功不可没)。

但是这种方式的问题在于:家庭数据中心内部的数据库还是存在单点故障;且跨广域网主从同步,延迟高的话可能会导致主从复制失败;另外我几天或者更长时间才有一次数据接入,搞这种同步有点大炮打蚊子的感觉(并且还是通过广域网同步~),所以也pass了。
3、每个wordpress站点在本机都运行一个mariadb数据库

这种方式其实就是现在的方式,既在家庭数据中心内部形成数据库的冗余:主站点和备用站点一个部署在macmini上,一个部署在intermini上,每一个节点上都有wordpress和mariadb数据库,且每个节点的wordpress都读写本地的mariadb数据库。wordpress对外通过负载均衡实现主备冗余,2个mariadb数据库是独立的(当然,其实mariadb数据库也可以做负载均衡,只是我懒得折腾了,意义不大)。同时容灾站点也部署了wordpress和mariadb数据库,这样可以在家庭数据中心出问题的时候,不影响容灾站点wordpress的正常运转(容灾站点访问访问本地的数据库,和家庭数据中心内数据库无关),唯一的问题是如何保证所有节点数据库的即时更新(以前没想到太好的方法,只能依靠WPvivid备份插件)。

在有了chevereto的多点定时同步方案以后(参见文章:家庭数据中心系列 chevereto图床多节点定时自动同步教程),最后一点坑已经被填平,wordpress的同步也可以用相同的思路:在wordpress主站点通过syncthing完成到其他节点wordpress程序数据的同步以及导出的wordpress.sql文件的同步,然后其他wordpress节点分别完成各自mariadb数据库上对wordpress.sql文件的导入即可(理论上不管节点有多少都可以用相同的办法处理)。

关于及时性更新的问题,其实很好解决,卖个关子,后面慢慢说,不过在这之前,我要重新规划syncthing方案里同步的wordpress文件夹。

部署syncthing同步wordpress文件夹

以前syncthing里wordpress同步的文件夹只是WPvivid备份插件的文件夹(主要是为了同步wordpress主站点WPvivid插件定时保存到本地的备份文件到其他节点WPvivid插件目录,方便有需要时候进行一键恢复),而现在要改成同步主wordpress站点使用-v参数挂载到docker的整个目录”html”:
image.png

syncthing的配置细节参看以前的文章:docker系列 使用docker基于syncthing实现多点文件夹同步之详细教程,我这里就不重复写了,为了后续试验,这次syncthing新增了一个aliyun节点,其docker run命令格式如下:

docker run --name syncthing-aliyun  -d --restart=always --net=public-net \
  --hostname=syncthing-aliyun \
  -e TZ=Asia/Shanghai \
  -p 8384:8384 \
  -p 22000:22000/tcp \
  -p 22000:22000/udp \
  -p 21027:21027/udp \
  -v /docker/syncthing/config:/config \
  -v /docker/wordpress:/data1 \  
  lscr.io/linuxserver/syncthing:latest

在同步源syncthing-macmini上使用tailscale的地址添加该节点,并在所有节点上都完成对wordpress文件夹的同步设置。
1、syncthing-macmini上的效果:

image.png

2、syncthing-intermini上的效果:
image.png

3、syncthing-tc上的效果:
image.png

4、syncthing-aliyun上的效果:
image.png

只要达到这个状态之后,syncthing的后续同步就基本不会出问题了,最麻烦的一步终于弄完了。

四个注意点:
1、映射到容器内部的目录,比如上面命令中的/docker/wordpress,一定要在每个节点的宿主机里将wordpress文件夹的权限改为777,否则无法同步。
2、如果出现这种报错:
image.png

可以在wordpress文件夹里手动新建一个名为”.stfolder”的文件夹来解决:

image.png

3、如果其他节点上wordpress文件夹状态不是”同步完成”:
image.png

而是红色的”失去同步”,那先找找失败的原因:
image.png

image.png

最终能用的招数就是改权限、移除失去同步syncthing节点上的文件夹,删除文件夹里的内容、重启syncthing容器,然后添加”.stfolder”文件夹,从主机上重新共享这么来回折腾,直到最后所有状态都正常。
4、建议除了主wordpress节点,其他节点直接把wordpress文件夹清空(如果原本有文件的话),然后新建好”.stfolder”文件夹后再开始从主节点上开始添加共享文件夹并完成同步。

注:syncthing可能还有其他报错,大家多在网上搜搜,文章还是挺多的,我这里肯定不能包括所有问题。

部署和初始化mariadb

然后是数据库的问题,因为各个wordpress节点的”wp-config.php”配置文件都是一样的,比如:
image.png

所以要保证每个节点上wordpress访问mariadb数据库的方式都是一样(在本文中就是都可以通过mariadb01进行访问),一般正常的方式是新建数据库的时候,将mariadb数据库的docker和wordpress的docker都放置于同一个非默认bridge里,如上面新建阿里云节点的syncthing里命令里的--net=public-net一样,然后要保证所有节点上mariadb的docker名字都和”wp-config.php”里设置的一样,我这里都是mariadb01:

image.png

mariadb01的创建命令参考如下:

docker run --name=mariadb01 -d --restart=always --net=public-net \
  -p 3306:3306 \
  -v /docker/mariadb/db:/var/lib/mysql \
  -e MARIADB_ROOT_PASSWORD=yourpassword \
  mariadb:10.11

创建完每个节点的mariadb数据库之后,还需要初始化的动作:创建wordpress的库以及库对应的账号密码,并将wordpress库的访问权限授予该账号(初始化库的相关操作参见文章:奇技淫巧系列 新建空数据库以及给对应用户赋予权限,当然,也可以使用大家自己熟悉的方式初始化,比如命令行、phpmyadmin等)。

mariadb数据库同步

主站点wordpress数据库导出

有了chevereto数据库同步经验之后,我还是采用相同的方式:将主wordpress站点上的mariadb数据库里的wordpress库导出到syncthing配置的wordpress同步文件夹里新建的DB目录中:

image.png

新建”export_wordpress_database.sh”脚本进行导出,脚本内容如下:

#!/bin/sh

# 远程ssh登录默认不会加载环境变量,主动加载一下,这是为了远程ssh执行此脚本做的准备,本地运行脚本不需要
source ~/.bash_profile

# 执行导出wordpress库命令,导出到已经配置了syncthing同步的wordpress/db文件夹里
docker exec -u root mariaDB01 mysqldump -uroot -pyourpassword --databases wordpress > /Volumes/data/docker/wordpress/db/wordpress.sql

# 运行完成
echo 'end'

不要忘记给脚本赋予执行权限:

chmod +x export_wordpress_database.sh # 需要进入正确的路径下执行

然后将脚本放置到任意路径下,比如我是在macos用户目录下新建的”startup”目录下,所有需要远程ssh运行的脚本我都是放这个目录下,便于管理,如下图:
image.png

现在只需要运行这个脚本,就可以在wordpress/db目录下生成主wordpress站点上wordpress库的全量备份文件wordpress.sql,只要前面syncthing同步目录配置正常,wordpress.sql文件就能很快同步到其他所有wordpress站点的DB目录中:

image.png

主wordpress站点(macmini):
mac_1716602958964.png

备用wordpress站点(intermini):
image.png

容灾wordpress站点(腾讯云服务器):
image.png

注:syncthing有自己默认的间隔扫描时间(3600秒),最终完成数据同步的时间,和需要同步的文件的大小以及各个syncthing节点的连接速率不同而不同,我这里wordpress数据库几十兆,感觉最多1-2分钟,所有节点都能同步完成,不过这是扫描到改变后的时间,至于什么时候开始扫描就要看脸了,只能保证3600秒之内一定能扫到~。

其他节点mariadb里实现wordpress库的导入

还是要依靠shell脚本来完成,在除了主wordpress站点以外的所有其他wordpress节点上的mariadb挂载文件夹中新建脚本”wordpress_import.sh”,内容如下:

#!/bin/sh

mysql -uroot -pp@ssw0rd  < /var/lib/mysql/wordpress.sql

# 运行完成
echo 'end'

该脚本要在mariadb容器中运行,将本地路径/var/lib/mysql/下的主wordpress站点同步过来的wordpress.sql文件导入到本地mariadb中。

注1:为什么<左边为空?因为前面通过mysqldump命令使用--database wordpress参数导出的wordpress.sql文件里是包含了create wordpress等命令,如下:

image.png

所以可以不用指定。另外不要忘记了赋予其执行权限:

chmod +x wordpress_import.sh # 需要进入正确的路径下执行

注2:为什么要把脚本”wordpress_import.sh”新建在mariadb的挂载文件夹中?因为无法在mariadb容器里直接导入宿主机文件系统上的文件,所以需要变通一下。

然后新建shell脚本”import_wordpress_database.sh”,内容如下:

#!/bin/sh

# 远程ssh登录默认不会加载环境变量,主动加载一下,这是为了远程ssh执行此脚本做的准备,本地运行脚本不需要
source ~/.bashrc  #注意,不同系统环境变量文件名不同,例如:macos是bash_profile,debian是bashrc,请根据自己实际环境修改

# 直接删除wordpress库,删表太麻烦了,而且怕某个版本变动增加新表,不过貌似不用删也行
docker exec -u root mariadb01 mysql -uroot -pyourpassword -e "drop database if exists wordpress;" 

# 将同步过来的wordpress.sql复制到mariadb的工作目录中,这就是上面说的变通
cp /docker/wordpress/db/wordpress.sql /docker/mariadb/db/01/wordpress.sql

# 将主wordpress站点导出的wordpress.sql导入本地mariadb数据库中
docker exec -u root mariadb01 bash /var/lib/mysql/wordpress_import.sh

# 运行完成
echo 'end'

脚本放在你习惯的路径,我直接放在/root/script目录下。

上述操作完成以后,只需要运行/root/import_wordpress_database.sh这个脚本,就可以完成:
第一步:删除本节点mariadb数据库中的wordpress库(其实貌似不要这步也行,只是这样干净点);
第二步:将/docker/wordpress/db里最新的wordpress.sql文件拷贝到mariadb容器本机的挂载目录
第三步:在mariadb容器之中导入wordpress.sql。

在其他节点部署wordpress

经过前面的步骤,除了主wordpress节点以外的其他wordpress节点上wordpress程序文件以及数据库都同步完成了,如果这些节点本来就部署了wordpress节点,已经可以直接访问了。因为我的阿里云节点是新增的,所以需要部署wordpress的容器,只需要用以下命令:

docker run --name=wordpress -d --restart=always --net=public-net \
-p 80:80 \
-v /docker/wordpress/html:/var/www/html  \ #注意挂载的wordpress文件夹路径不要出差
wordpress

然后直接访问就可以了。

注:默认wordpress限定了访问域名,如果要去除访问限制,请参考我另一篇文章:奇技淫巧系列 wordpress支持多域名访问功能简易设置教程

使用inotify监控文件夹变化并执行脚本

流程逻辑

其实前面的步骤,全都是人工操作,只能算wordpress多节点同步方案,和我标题提到的”近乎”实时同步方案不沾边啊。的确是,所以接下来就是重点了:inotify。

inotify是一个linux下的监控文件夹变化的工具,其可以监控文件夹内容变化,然后执行指定的脚本,这不就和我们前面的操作关联起来了嘛:当我在主wordpress站点上运行了导出wordpress库的脚本”export_wordpress_database.sh”,就会在主站点的”wordpress/db”目录中生成一个新的wordpress.sql脚本;新的wordpress.sql脚本生成被syncthing发现并同步到所有的其他wordpress节点上的db目录中;在其他wordpress节点上运行的inotify监控本地节点上的”wordpress/db”文件夹,一旦发现发生了变化,就执行本地的”import_wordpress_database.sh”脚本,完成wordpress库的导入,然后所有节点的wordpress同步完成,完美!

安装部署inotify

apt update
apt install inotify-tools

安装完成后,就可以使用inotifywait和inotifywatch这两条命令,其中,inotifywait就是我们要使用来监控wordpress/db文件夹的变化的,inotifywatch是统计文件系统的访问次数,这里用不上。

我们需要编写一个脚本”monitor.sh:,内容如下:

#!/bin/bash
watchdir="/docker/wordpress/db"  # 定义需要监控的内容,我这里就监控db目录
script="/root/import_wordpress_database.sh" #定义需要执行的脚本
while 
inotifywait -e modify $watchdir; # -e modify dir是监控dir目录下是否有文件被修改 -o modifylog是将监控到的事件(这里是文件被修改)写到modifylog日志中
do
timestamp=$(date)
sleep 1m # 等待1分钟,因为通过syncthing同步完文件需要一点时间,如果不等待就会一直记录文件修改
bash $script # 执行脚本导入wordpress.sql文件
done

授予执行权限:

chmod +x monitor.sh

然后将monitor.sh加入开机启动即可(参见我另一篇文章:debian系列 设置命令或脚本开机启动的3种常见方式)。
最后确保所有其他wordpress节点上都正常运行了monitor.sh:

image.png

image.png

image.png

验证方案实际效果

1、在主wordpress节点上执行脚本”export_wordpress_database.sh”
image.png

进入导出目录进行确认:

image.png

2、验证syncthing是否成功同步

由于默认syncthing重新扫描时间是1小时,我不想等这么久,所以点重新扫描(注意我点的时间是08:06):
image.png


从导出时间08:01到08:06之间我干什么去了?是因为我的小熊煮蛋器蜂鸣提醒鸡蛋煮好了 ,我先去吃了个早餐。。

其实这个时候如果syncthing运行正常,同步基本瞬间就已经完成(主要是wordpress.sql文件不大,才38兆),在initofywait的终端窗口是看得到文件夹modify event信息的,以阿里云节点为例:
image.png


然后我们依次到到其他节点上去确认,首先确认syncthing同步是否成功。
备用站点:

image.png

腾讯容灾站点:

阿里容灾站点:

image.png

可见syncthing的同步都成功了。

最后来确认inotifywait是否成功监控到了/docker/wordpress/db文件夹下wordpress.sql文件的变化并执行了脚本”import_wordpress_database.sh”。如果按照脚本执行内容:
image.png

那么我们依次看几个节点上/docker/mariadb/db/01/wordpress.sql文件的修改时间(其实应该看最后一个命令docker exec -u root mariadb01 bash /var/lib/mysql/wordpress_import.sh的执行情况,但是这个执行结果我一下子想不到什么好的证明方式,感觉都不够权威,所以还是看看上一步的wordpress.sql的生成时间)。
备用节点:

image.png

腾讯节点:
image.png

阿里节点:

image.png

基本就是我点击syncthing wordpress文件夹的”重新扫描”按钮(08:06)之后的一分钟,这证明了inotifywait的确可以监控/docker/wordpress/db文件夹的变化并执行了指定的脚本:
import_wordpress_database.sh,补上了我的:wordpress多节点"半自动"、"近乎"实时同步方案的最后一块拼图。

注1:所谓”半自动”是指需要我在完成主wordpress站点内容更新之后,手动运行一个数据库导出的脚本”export_wordpress_database.sh”,而剩余的都是全自动。讲道理,”半自动”有点谦虚了,应该是”0.9自动”,不过终究离”全自动”还是有差距的。要想实现全自动也不是不可以,不过还需要继续深入研究wordpress的工作原理,主要是如何判断wordpress更新了内容(文章、说说、页面)等,因为插件、wordpress版本都可以自动更新,这些不能作为判断依据(其实可以从判断数据库新增内容入手,卧槽,想着就刺激)。

我就是想到这里就犯嘀咕了,实在是不想再深入研究了,干脆就用手动运行脚本输出wordpress.sql文件到指定文件夹来触发后续流程,其实也违背了我”有困难要上,没有困难创造困难也要上的原则了”,但是真太累了,伤我脑细胞,以后有心情的时候再继续研究吧。

另:经过了一段时间使用,还是不能直接同步wordpress的整个html目录,主要是因为主节点版本升级或者插件更新等原因,直接同步整个html目录到其他节点经常会引起wordpress的”致命错误”,最好的方式还是只同步wordpress.sql这个文件所在的目录,这样以后就只是单纯的wordpress数据库的导出、文件同步、导入,这就没问题了。

注2:所谓”近乎”实时同步,是因为syncthing完整扫描一次默认是1小时(有点看运气,有时候很快就扫描到了,有时候半天也没反应,所以我在试验的时候才手动去点”重新扫描”的按钮),1小时对我的需求而言完全可以接受,毕竟只是个人博客,也不是什么企业级的高标准应用,所以我也懒得去改了,如果有朋友真要高标准要求,把syncthing的”完整扫描间隔”改小就行:
image.png

总结

其实吧,如果只是要在多个wordpress站点之间实现发布文章同步,有更简单的方法:比如使用插件,这种插件还不止一个,虽然也有些设置,而且使用效果也有不少缺陷,但是和我这个方法比起来,真的要简单很多。并且我以前用的”基于WPvivid备份插件定时备份和syncthing同步配合再加上需要时人工恢复”的方法(这么长的定语还是感觉颇low),要说也不是不能用。

但是吧,对于我而言,通过不停折腾、不停学习新技术(比如这篇文章就逼我研究shell脚本),不停优化方案,哪怕每次只是一点点提升,学到了一点点新知识,但是日积月累之后,说不定哪天就神功大成了呢!(葵花在手,哈哈哈哈,江山我有,哈哈哈哈,很熟悉有没有?)
image.png

image.png

当然,如文章开头所说,这篇文章只能算是前置技术的研究,最终还是要研究:”白嫖cloudflare free计划的tunnel实现多节点wordpress就近访问及容灾解决方案”,也不知道行不行,不过先研究研究看看吧。

博客内容均系原创,转载请注明出处!更多博客文章,可以移步至网站地图了解。博客的RSS地址为:https://blog.tangwudi.com/feed,欢迎订阅;如有需要,可以加入Telegram群一起讨论问题。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇
       
error:
zh_CN
春节
快乐