3、PostgreSQL深度解析:PostgreSQL特性、在ThingsBoard中的角色、安装与配置、主从复制方案

好,咱们进入第三讲。这一章我打算把PostgreSQL彻底聊透。为什么?因为它是ThingsBoard的默认数据库,也是生产环境中最靠谱的选择。我见过太多团队在数据库选型上翻车,最后灰溜溜地换回PostgreSQL。说白了,选它不一定最潮,但一定最稳。

3.1 PostgreSQL核心特性:为什么ThingsBoard选它?

先说说PostgreSQL的几个硬核特性。我个人习惯把它叫做“数据库界的瑞士军刀”——功能太全了。

  • ACID事务:完全支持,而且实现得很扎实。我在项目中遇到过并发写入导致数据错乱的情况,换成PostgreSQL后问题迎刃而解。
  • 扩展性:支持自定义数据类型、函数、索引类型。ThingsBoard就用到了它的JSONB类型来存储设备属性。
  • MVCC(多版本并发控制):读不阻塞写,写不阻塞读。这对IoT场景太重要了——你想想看,设备数据一直在写,用户同时要查报表,如果读写互相锁死,系统就崩了。
  • 强大的索引:B-tree、Hash、GiST、GIN、BRIN……特别是BRIN索引,对时序数据非常友好。
  • 流复制:原生支持主从复制,配置简单,延迟低。

核心观点:PostgreSQL在ThingsBoard中扮演的是“持久化基石”的角色。所有设备元数据、用户信息、规则链定义、告警记录都存这里。时序数据虽然可以交给Cassandra或TimescaleDB,但元数据这块,PostgreSQL是雷打不动的。

3.2 PostgreSQL在ThingsBoard中的具体角色

ThingsBoard的架构里,PostgreSQL主要负责三块内容:

  1. 实体数据:设备、资产、租户、用户、仪表板、规则链等。这些数据量不大,但关系复杂,用关系型数据库管理最合适。
  2. 最新遥测数据:每个设备的最新属性值、最新遥测值。ThingsBoard用了一张专门的表来存“最新值”,方便快速查询。
  3. 告警与事件:告警记录、审计日志、事件数据。这些需要支持复杂查询和关联。

嗯,这里要注意:时序数据(历史遥测)默认也可以存PostgreSQL,但生产环境我建议别这么干。数据量一上来,查询性能会急剧下降。我踩过这个坑——当时一个项目每天产生500万条遥测数据,PostgreSQL撑了三天就扛不住了。后来切到TimescaleDB才解决。

3.3 安装与配置:从零开始搭一个稳当的环境

安装PostgreSQL其实不难,但配置才是关键。我直接上干货。

3.3.1 安装

以Ubuntu 20.04为例:

# 安装
sudo apt update
sudo apt install postgresql postgresql-contrib

# 检查状态
sudo systemctl status postgresql

# 进入命令行
sudo -u postgres psql

安装完成后,记得设置密码:

ALTER USER postgres WITH PASSWORD 'your_strong_password';

3.3.2 配置优化

配置文件在 /etc/postgresql/14/main/postgresql.conf。我一般会改这几个参数:

参数 推荐值 说明
shared_buffers 内存的25% PostgreSQL自己的缓存,别设太大,要给OS留空间
effective_cache_size 内存的50%-75% 告诉优化器OS能缓存多少数据
work_mem 4-8MB 排序和哈希操作的内存,设太大容易OOM
maintenance_work_mem 64-256MB VACUUM、CREATE INDEX等维护操作
wal_buffers 16-64MB WAL日志缓冲区,写入频繁时调大
max_connections 100-200 ThingsBoard默认连接池不大,够用就行

我的经验:对于ThingsBoard,shared_buffers设到内存的20%就差不多了。我曾经给一台32G内存的服务器设了12G,结果系统频繁swap,性能反而下降。记住,PostgreSQL依赖OS的文件系统缓存,别把内存全占了。

3.3.3 创建ThingsBoard数据库

CREATE DATABASE thingsboard;
CREATE USER tb_user WITH PASSWORD 'tb_password';
GRANT ALL PRIVILEGES ON DATABASE thingsboard TO tb_user;

-- 别忘了给public schema授权
\c thingsboard
GRANT ALL ON SCHEMA public TO tb_user;

3.4 主从复制方案:高可用的基石

单机PostgreSQL扛不住生产环境。一旦挂了,整个ThingsBoard就瘫了。所以主从复制是必须的。

3.4.1 流复制原理

PostgreSQL的流复制,说白了就是主库把WAL日志实时传给从库,从库重放这些日志。延迟通常在毫秒级。

我习惯用异步复制,性能好,丢数据的概率极低。如果对数据一致性要求极高,可以用同步复制,但性能会下降30%左右。

3.4.2 配置步骤

主库配置

# postgresql.conf
wal_level = replica
max_wal_senders = 5
wal_keep_size = 1024    # 保留1GB的WAL日志,防止从库追不上

# pg_hba.conf 添加从库IP
host replication repl_user 192.168.1.0/24 md5

创建复制用户

CREATE USER repl_user WITH REPLICATION PASSWORD 'repl_password';

从库配置

# 先停掉从库的PostgreSQL
sudo systemctl stop postgresql

# 清空从库数据目录
rm -rf /var/lib/postgresql/14/main/*

# 从主库拉取基础备份
pg_basebackup -h 主库IP -U repl_user -D /var/lib/postgresql/14/main/ -P -R

# 启动从库
sudo systemctl start postgresql

这里的 -R 参数会自动生成 standby.signal 文件,告诉PostgreSQL这是从库。

3.4.3 验证复制状态

在主库执行:

SELECT * FROM pg_stat_replication;

如果看到一行记录,说明复制正常。重点关注 write_lagflush_lag 字段,正常情况下应该在毫秒级。

避坑指南:我曾经遇到一个坑——从库复制延迟越来越大,最后差了十几分钟。查了半天发现是主库的 wal_keep_size 设得太小,从库断连后WAL日志被清理了。解决办法是调大 wal_keep_size,或者启用复制槽(pg_create_physical_replication_slot)。

3.4.4 故障切换

主库挂了怎么办?手动提升从库为主库:

# 在从库执行
pg_ctl promote -D /var/lib/postgresql/14/main/

然后修改ThingsBoard的配置文件,把数据库连接指向新的主库。如果用了HAProxy或Pgpool-II,可以自动切换,但那是进阶话题了。

3.5 小结

PostgreSQL在ThingsBoard里,就像地基之于房子。地基不稳,上层建筑再花哨也没用。我个人建议:

  • 开发环境用单机PostgreSQL就够了
  • 测试环境至少配一主一从
  • 生产环境建议一主两从,再加一个Pgpool-II做负载均衡

下一章咱们聊TimescaleDB——专门为时序数据设计的数据库,和PostgreSQL配合起来,堪称ThingsBoard的黄金搭档。