3步搭好 ThingsBoard 多租户备份,附恢复演练脚本
2026/9/6 17:10:54 网站建设 项目流程

3步搭好 ThingsBoard 多租户备份,附恢复演练脚本

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

上个季度一次生产环境升级后,某租户的历史时序数据全部丢失——排查发现上一版"备份"只是把 data 目录整包 tar 了一下,表结构变更后根本导不回去,几个 TB 的备份等于没做。这是跳过 ThingsBoard 多租户备份最典型的代价:备份文件在,但真出事时不可用。下面给你一套"备份 → 调度 → 校验"的闭环,30 分钟能搭完,并且每个环节都有可验证的结果。

动手之前的三件事:10分钟确认环境与前置条件

确认项确认方式合格标准
数据库类型与权限thingsboard库的连接配置,确认账号PostgreSQL 或 TimescaleDB,备份账号有pg_dump权限
租户表命名规则information_schema列一遍ts_%attributesdevice等表时序数据在ts_kv族(按年分区表 +ts_kv_latest最新值表),attributesdevicecustomer等实体表都带tenant_id列,可按租户行级过滤
调度入口crontab -l/systemctl list-timerscrontab 或 systemd timer 任选其一,不必依赖平台内置调度

核心配置在 application/src/main/resources/thingsboard.yml,数据库连接段里的账号要和 Docker 编排侧保持一致,可对照 docker/docker-compose.yml 里的 postgres 服务。租户数据的存取逻辑都在 DAO 层,dao/src/main/java/org/thingsboard/server/dao/tenant/ 下的TenantDao可以帮你核对"哪些表属于租户、哪些要按tenant_id过滤"。

你要保护的就是这类控制台里的数据:

三步搭好"备份 → 调度 → 校验"闭环

第1步:按租户行级导出,12行脚本

这段脚本解决"只导这一个租户的数据":租户私有表整表 dump,共享表按tenant_id行级导出,避免把别的租户数据卷进来。

#!/usr/bin/env bash set -euo pipefail TID=$1; DB=thingsboard OUT="backups/${TID}_$(date +%Y%m%d_%H%M%S)"; mkdir -p "$OUT" # 租户私有表:整表导出 docker exec tb_postgres pg_dump -U postgres -d $DB \ -t tenant -t customer -t device -t rule_chain \ --data-only -f /tmp/tb_tenant.sql docker cp tb_postgres:/tmp/tb_tenant.sql "$OUT/" # 共享表:按 tenant_id 行级导出 docker exec tb_postgres psql -U postgres -d $DB -c \ "COPY (SELECT * FROM attributes WHERE tenant_id='$TID') TO STDOUT" > "$OUT/attributes.csv"

ts_kv按年分区表数据量最大,建议另起循环按年份分区逐张导出并归档到同一目录。执行完你应该看到backups/<租户ID>_日期目录下有tb_tenant.sqlattributes.csv等文件,且非空。

第2步:crontab 一行搞定每日备份

30 2 * * * /opt/tb-backup/backup_all_tenants.sh >> /var/log/tb-backup.log 2>&1

backup_all_tenants.sh的逻辑一句话带过:从库里查出所有租户 ID,循环调用第 1 步脚本,最后find -mtime +30 -delete清掉 30 天前的旧备份。✅ 次日 2:30 后你应该看到/var/log/tb-backup.log末尾新增一行日志,且backups下出现当天新目录。

第3步:10行代码验证备份完整性

这段校验解决"备份文件在 ≠ 数据全":源库行数与导出文件行数直接比对,差一行就判失败。

SRC=$(docker exec tb_postgres psql -U postgres -d $DB -tAc \ "SELECT COUNT(*) FROM attributes WHERE tenant_id='$TID'") F=$(wc -l < "$OUT/attributes.csv") if [ "$SRC" -eq $((F-1)) ]; then echo "OK $TID" else echo "FAIL $TID" >> /var/log/tb-backup-error.log fi

输出OK <租户ID>才算这次备份合格;FAIL行写进错误日志,配合 monitoring/src/main/resources/tb-monitoring.yml 所在的监控模块可以配成告警,失败当天就能发现。

恢复演练:确认备份真的能用

没做过恢复演练的备份等于没有备份。演练不用碰生产库,一个临时库就够:建库 → 导入 → 比行数。

TEST="tb_restore_drill_$(date +%s)" F="backups/${TID}_20250601_023000" docker exec tb_postgres psql -U postgres -c "CREATE DATABASE $TEST" docker exec -i tb_postgres psql -U postgres -d $TEST \ -c "COPY attributes FROM STDIN WITH CSV HEADER" < "$F/attributes.csv" docker exec tb_postgres psql -U postgres -d $TEST -tAc \ "SELECT COUNT(*) FROM attributes" docker exec tb_postgres psql -U postgres -c "DROP DATABASE $TEST"

最后查出的行数应与第 3 步记录的源库行数一致,然后删掉临时库。这就是租户在界面上看到的数值来源,演练一次比检查十次文件更有说服力:

建议把"每季度对抽样租户做一次恢复演练"写进运维 SOP,记录演练日期与行数比对结果;一次真实事故里,能救命的只有演练过的那个备份。

踩坑与调优清单:高频问题的现象-原因-处理

  1. 备份窗口超过 4 小时ts_kv按年分区表太大且pg_dump单线程 → 按年份分区拆任务、多租户用xargs -P 4并行,窗口挪到业务低峰。
  2. 数据盘被备份撑满,库直接挂→ 备份目录和库数据在同一卷 → 备份放独立卷(参考 docker/docker-compose.volumes.yml 的卷挂载方式)再同步到异地 S3;保留策略用每日 30 天 + 每月 12 个月。
  3. REST API 拉租户列表 401→ JWT 过期或账号不是系统租户 → 别走 API,直接SELECT id FROM tenant查库,少一整类鉴权问题。
  4. 恢复后行数比源库少→ 只 dump 了ts_kv主表,漏了按年分区表 → 用information_schema枚举所有ts_kv%表放进导出清单。

存储策略和并行化点到为止:卷、S3、xargs三件套够用,不必上更重的方案。

备份能恢复,才算合格。先跑通三步闭环,再做一次真实恢复演练,写进 SOP。想深挖租户数据模型,从 dao/src/main/java/org/thingsboard/server/dao/tenant/ 看起。

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

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

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

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

立即咨询