在法国用二手 NAS 跑 Home Assistant,别把数据库放 SD 卡
Freebox Pop 后面那台 DS218j,2GB 内存,DSM 7.1,插着一块 4TB 西数红盘。去年冬天开始用 Docker 跑 Home Assistant,镜像版本 2024.1 左右,接入的实体不多,二十来个:几个 Zigbee 插座、两个温湿度传感器、一个 Netatmo 的天气模块,再加 Freebox 的 DSL 状态。数据量很小,recorder 默认只保留 10 天,数据库撑死几百兆。
问题出在启动速度和历史查询上。HA 的容器目录我一开始放在 NAS 的机械盘上,SQLite 的 home-assistant_v2.db 也跟着躺在那里。每次重启,日志里 recorder 那段要磨二十多秒,查前一天的温湿度曲线,手机端转圈能转到我以为它卡死。后来把容器目录挪到一块 32GB 的 U 盘上——想着 U 盘再慢也比机械盘寻道快——结果更糟,两周后 U 盘开始报 I/O 错误,HA 直接起不来。
最后的做法是把数据库单独拎出来,放内存盘,再定期落盘:
# docker-compose.yml 片段
services:
homeassistant:
image: ghcr.io/home-assistant/home-assistant:stable
volumes:
- /volume1/docker/ha/config:/config
- /dev/shm/ha-db:/config/db
environment:
- TZ=Europe/Paris
配置里把 recorder 的 db_url 指到 /config/db:
recorder:
db_url: sqlite:////config/db/home-assistant_v2.db
purge_keep_days: 7
再在 NAS 的计划任务里每天凌晨跑一次备份,把 /dev/shm/ha-db 下的文件 rsync 回机械盘。DS218j 的 /dev/shm 默认只有 64MB 左右,我确认过实际可用大概 60MB,所以 purge_keep_days 从 10 压到 7,实体也关掉了几个不看的。
为什么这样做:SQLite 的写入模式对随机 I/O 很敏感,机械盘上每次 commit 都要等磁头,U 盘则是寿命和掉盘风险。内存盘把这两样都绕开了,代价是断电会丢最近一次落盘之后的数据,最长一天。对温湿度这种历史数据,我能接受。
哪里会失效:一是 /dev/shm 太小,实体一多、保留天数一长,数据库涨过 60MB 就会写失败,recorder 会在日志里刷 disk I/O error,HA 表面还能跑但历史全空;二是 rsync 备份如果正好赶上 SQLite 在写,拷出来的文件可能不一致,我现在是先停容器再拷,麻烦但稳;三是我试过把 db 放 tmpfs 的同时把 logbook 也开满,内存直接吃紧,NAS 的 Web 界面都变慢,后来把 logbook 关了。
如果你也在法国这边用老 NAS 跑 HA,Freebox 的 DHCP 租约和 Zigbee 网关的 IP 记得在路由器里固定,不然重启后实体全变 unavailable,还得一个个改。你们那边 recorder 保留几天,数据库大概多大?
0 条评论
还没有评论,写下第一条。