ThingsBoard 多租户备份:凌晨自动跑,数据坏了也能按租户找回
2026/9/6 21:06:26 网站建设 项目流程

ThingsBoard 多租户备份:凌晨自动跑,数据坏了也能按租户找回

【免费下载链接】thingsboardOpen-source IoT Platform - Device management, data collection, processing and visualization.项目地址: https://gitcode.com/GitHub_Trending/th/thingsboard

如果你在用 ThingsBoard 给多个客户跑设备平台,最怕的就是手动备份做到一半断掉,第二天发现某个租户的历史遥测数据没了着落。这套流程把"按租户备份"变成每天半夜自己跑的任务。

不做自动备份,坑长什么样

  • 手动 pg_dump 导到一半网络断了,留下的文件是半份表,你根本不知道它缺了哪几张;
  • 客户要求"只回滚我们租户最近一周",可你手里只有全库快照,没有能单独拿出来恢复的租户级文件;
  • 磁盘坏掉时花两小时灌完备份,最后发现 .sql 打不开——平时压根没验证过。

这三件事的共同点:备份"存在"不等于备份"可用"。

整体思路

先把链路想清楚,数据从哪来、存到哪、怎么确认没丢:

数据源是容器里的 PostgreSQL(设备、租户、ts_kv 时序表都在里面)→ 用 pg_dump 按 tenant_id 切片导出成 .dump 文件 → 落到主机上的 backups 目录 → 定期"恢复到空库再数行数"验证 → 失败就写错误日志,让你知道哪份备份不可信。

tenant_id 说白了就是每个租户在平台上的唯一编号,几乎所有业务表都带这一列,这正是我们能按租户切片的根本原因。

落地步骤

先从数据库里把租户ID清单捞出来

做完这一步,你会拿到"一行一个租户ID"的清单,后面脚本直接拿它循环。

# 查 tenant 表,输出纯文本,每行一个 UUID docker compose exec -T postgres psql -U postgres -d thingsboard -Atc \ "select id::text from tenant"

-Atc关掉表头只出裸数据;id::text是因为 UUID 直接打印会带括号,转成字符串方便 shell 循环。tenant 表就是租户数据的入口,它的增删改查逻辑可以参考 租户 DAO 模块。

清单拿到手,接下来把它交给备份脚本。

写一个按租户切片的备份脚本

做完这一步,每个租户对应一个独立 .dump,单租户坏了不影响别人,恢复时也只灌自己的那份。

#!/usr/bin/env bash # 按租户切片备份:靠 tenant_id 过滤,产物可单独恢复 set -euo pipefail STAMP=$(date +%F_%H%M) OUT_DIR="./backups/${STAMP}" mkdir -p "$OUT_DIR" # 从 tenant 表拿全部租户ID docker compose exec -T postgres psql -U postgres -d thingsboard -Atc \ "select id::text from tenant" | while read -r tid; do # -Fc:自定义压缩格式,恢复时可挑表、可并行 # --where:给列出的每张表都加租户过滤,只导这一个租户的行 docker compose exec -T postgres pg_dump -U postgres -d thingsboard \ -t ts_kv -t ts_kv_latest -t device -t device_credentials \ --where "tenant_id in ('${tid}')" \ -f "/tmp/tb_${tid}.dump" docker compose cp postgres:/tmp/tb_${tid}.dump "${OUT_DIR}/" done echo "备份完成: ${OUT_DIR}"

两个关键参数值得留意:-Fc产出自定义格式,恢复时能挑表、能并行;--where只对-t显式列出的表生效,所以想按租户切的表都要列全。如果你的 compose 里 postgres 服务名不叫 postgres,改脚本里那一处就行。

脚本手动跑通之后,剩下就是让它别依赖人记得。

让 crontab 每天半夜自己跑

做完这一步,每天 02:30 备份自动执行,stdout 和报错全进独立日志,你只需要偶尔翻一眼。

# crontab -e 加这一行:02:30 跑备份,日志单独落盘 30 2 * * * /opt/tb-backup/run_backup_all.sh >> /var/log/tb_backup.log 2>&1

时点选在设备上报的低峰期。pg_dump 走的是 MVCC 一致性快照,不需要停写,但半夜跑对线上查询的压力最小。

验证与兜底

备份这件事,本质是给自己买个保险:不验证过的备份,等于没备份。

恢复测试怎么做才靠谱:把某份 .dump 灌进一个全新的空库,再和源库当时的行数对比,一致才算数。

#!/usr/bin/env bash # 恢复演练:空库 + 行数比对 DUMP=$1 # 待验证的 .dump TID=$2 # 对应的租户ID createdb tb_restore_check pg_restore -d tb_restore_check "$DUMP" NEW=$(psql -d tb_restore_check -Atc "select count(*) from ts_kv") OLD=$(docker compose exec -T postgres psql -U postgres -d thingsboard \ -Atc "select count(*) from ts_kv where tenant_id in ('$TID')") [ "$NEW" = "$OLD" ] && echo "验证通过" || \ { echo "$(date) 行数不一致: ${TID}" >> /var/log/tb_backup_error.log; exit 1; }

每周挑一两个租户跑一遍就够,不用天天来。

备份失败怎么第一时间知道:脚本里的set -e保证任何一步挂掉就整体退出,再在退出路径上把租户ID和时间戳追加进/var/log/tb_backup_error.log。然后配个最简单的巡检:每天早上用 cron 检查这个错误日志有没有新增行,有就发邮件或丢到 IM 群。如果你已经上了监控栈(docker 目录里有 prometheus-grafana 的 compose 文件),把这个错误日志接成告警规则更省事。

生产环境注意事项

  • 保留策略:每日备份留 30 天,月度备份留 12 个月,过期直接删,别让 backups 目录撑爆磁盘。
  • 每周加一次全量:按表切片只保数据,库结构变更、没列进-t的表,靠每周一次-Fc全库 dump 兜底。
  • 本地状态文件不走 pg_dump:队列和 EDQS 用的 RocksDB 状态是文件,靠拷贝目录备份,路径在 thingsboard.yml 里用TB_QUEUE_CF_ROCKS_DB_PATHTB_EDQS_ROCKSDB_PATH两个环境变量配置。
  • 留一份异地:本地盘和数据库同机,盘坏了备份跟着没,压缩包定期 rsync 或上传到对象存储。

跑通这套之后,你对"某租户数据坏了"的焦虑会小很多——凌晨自动导出、每周恢复演练、失败有日志可查。想确认哪些表和租户相关,直接翻 dao 模块里的 ModelConstants,表名和列名都定义在那里。

【免费下载链接】thingsboardOpen-source IoT Platform - Device management, data collection, processing and visualization.项目地址: https://gitcode.com/GitHub_Trending/th/thingsboard

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询