

万村乐数字乡村系统面向的是县、乡、村三级政务与民生场景,这类客户几乎都要求私有化部署。我们提供的买断版支持在客户自己的机房里无限部署,数据完全留在本地,做到自主可控。把系统从公有云 SaaS 搬到客户内网,好处是数据安全放心,代价是容灾这件事得自己扛:没有云厂商帮你看门,备份、异地副本、故障切换都要在交付方案里写清楚。下面把我们在 2024 年到 2026 年之间落地的备份与异地容灾做法拆开讲。
RPO 和 RTO 不是名词,是两条红线
做容灾第一步是把指标说人话。RPO(Recovery Point Objective)是"最多丢多少数据",RTO(Recovery Time Objective)是"最多停多久"。政务项目里这两个值一般会写进合同附件,而不是技术文档的漂亮话。
我们在县一级的部署中,给客户承诺的 RPO 目标是 15 分钟以内,RTO 目标控制在 2 小时以内。15 分钟意味着数据库必须持续有增量日志落盘并能被重放,2 小时意味着备机、配置、文件副本都得提前备好,不能等出事再现装。这两个数字不是拍脑袋,是按村级业务的实际容忍度倒推的:村务审批断 2 小时还能靠纸质先顶,但财务流水如果丢了 15 分钟以上,对账就没人敢签字。
数据库层:全量加增量,binlog 是命脉
万村乐 Java 版后端用 MySQL 8.0.28 存业务数据,连接池走 Druid 1.2.8。我们的备份策略分三层:
第一层是每日全量。用 Percona XtraBackup 在业务低峰(凌晨 2 点)做一次物理全备,直接写本地磁盘,再压缩转存。第二层是持续增量,靠 MySQL 的 binlog。第三层才是异地,后面单独讲。
开启 binlog 的配置在 my.cnf 里是硬要求:
sync_binlog = 1加innodb_flush_log_at_trx_commit = 1是双一配置,保证每条事务落盘,这是把 RPO 压到分钟级的前提。牺牲一点写性能,换的是故障时 binlog 能完整重放。
每日全量的调度脚本长这样:
这里用到了阿里云 OSS 作为异地载体。万村乐的文件存储本身支持本地、阿里云、腾讯云三种方式,我们顺手把备份也复用这套对象存储通道,避免再引入一套传输组件。
文件层:附件和图片比库更占地方
村里的照片、公示 PDF、便民服务附件,体量远大于结构化数据。万村乐的文件存储模块支持本地磁盘、阿里云 OSS、腾讯云 COS 三种后端,部署时我们一般让生产环境直接写本地盘,再异步同步到云上桶做异地副本。
这条命令卡在 10 分钟粒度,配合数据库的 15 分钟 RPO,整体数据丢失窗口基本对齐。如果客户有腾讯云账号,也可以把 uploads 直接配成 COS 后端,跨地域复制交给云厂商的存储冗余去做,我们这边只管配置和校验。
异地容灾:同城加异地两段式
政务客户普遍接受"同城热备 + 异地冷备"的两段式。同城放一台规格略低的主备机,MySQL 用主从复制实时追 binlog;异地只保留每日全量加周期性增量包,出大事才启用。
Druid 这边我们给只读报表流量单独指到从库,减轻主库压力,也顺带验证了从库数据可读:
切换时我们不做自动 failover,而是人工确认后改 DNS 或 Nginx upstream 指向备机。原因很直接:自动切换一旦误判,脑裂比宕机更可怕,县里运维人手有限,宁可多花 20 分钟人工核对,也不赌自动化的准确率。
演练比备份本身更重要
备份写了不等于能恢复。我们交付时必做两件事:一是随机抽一张全量包,在隔离环境xtrabackup --prepare后起库,用 count 校验行数;二是每季度拉一次异地包做一次真实恢复演练,把 RTO 实际跑出来记进运维报告。

有一次演练我们发现异地 OSS 上的某个增量包因为 ossutil 断点续传没跑完,文件大小对不上。如果真到故障那天才发现,RPO 直接破功。从那以后我们加了一条校验:每次推送完用 md5sum 比对源端和对象存储端的清单,不一致就告警重传。
备份健康度也要进监控
备份跑没跑成功,不能靠人天天看日志。我们在每个部署节点上挂了一个健康度检查,逻辑很简单:检查当天全量包是否存在、binlog 位点是否在推进、异地 OSS 清单 md5 是否匹配。
这个脚本放进 crontab 每天跑,告警直接进运维邮箱。它解决的不是技术难题,而是"备份 silently 挂了没人知道"这个最常见的容灾失效模式。我们见过不止一个项目,全量脚本因为磁盘写满悄悄退出,三个月没人发现,真出故障才暴露。
移动端不受影响的前提是后端先稳住
万村乐的移动端用 UNI-APP 打包,覆盖村民手机端和网格员采集端。端上断网能缓存待办,但本质上数据还是要回主库。所以容灾的优先级永远是后端数据库和文件存储,端只是受益方。我们把 RPO/RTO 的红线圈在后端,前端弱网和离线逻辑另文再聊。
几个踩过的坑
第一,binlog 保留天数别设太短。expire_logs_days 给过 3 天,结果一次恢复要追 4 天的量,只能先找更早的全量,RTO 直接超。现在统一 7 天起步。
第二,Druid 1.2.8 的连接泄漏在长事务下出现过,备库复制一度因为连接被打满而延迟。我们给连接池加了removeAbandoned和超时回收,从库延迟回到秒级。
第三,异地账号权限要最小化。曾经把 OSS 的写密钥直接写在脚本里提交到了内部仓库,后来全部改成环境变量加密钥管理,备份通道和 Production 业务账号彻底分开。

小结
政务类系统的容灾没有银弹,核心是把 RPO/RTO 翻译成可执行的备份分级:MySQL 8.0.28 开双一配置和 binlog 兜底增量,XtraBackup 每日全量,文件走本地加阿里云/腾讯云异地副本,同城主从实时追、异地冷备季度演练。万村乐的私有云部署模式让数据留在客户机房,相应的容灾责任也落在交付团队身上,把演练做成例程,比任何漂亮方案都实在。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。