从丢包到万级TPS:EMQX消息存储引擎深度测评(内置存储vs外部数据库)
你是否遇到过MQTT消息在设备离线后丢失的问题?当物联网设备数量突破10万级时,消息存储成为系统稳定性的关键瓶颈。本文将对比EMQX两种存储方案——内置持久化引擎(Retainer/Durable Storage)与外部数据库集成(MySQL/PostgreSQL等),帮助你在不同业务场景下做出最优选择。
存储引擎架构解析
EMQX提供双层消息存储架构,分别应对实时通信与持久化需求:
内置存储方案
- Retainer模块:轻量级消息缓存,用于存储最新的单条主题消息,支持快速订阅推送。配置文件位于retainer.conf,默认启用并存储在内存中,可通过磁盘持久化增强可靠性。
- Durable Storage:基于RocksDB的分布式存储引擎,支持消息的时序分片和精确一次投递。核心实现见emqx_durable_storage,采用数据库→分片→世代→流的四级组织结构,确保高并发写入下的存储效率。
外部数据库集成
通过规则引擎和数据桥接模块,EMQX支持将消息转发至20+种外部存储系统:
- 关系型数据库:MySQL(emqx_bridge_mysql)、PostgreSQL(emqx_bridge_postgresql)
- 时序数据库:InfluxDB(emqx_bridge_influxdb)、ClickHouse(emqx_bridge_clickhouse)
- 消息队列:Kafka(emqx_bridge_kafka)、RabbitMQ(emqx_bridge_rabbitmq)
性能测试对比
基准测试环境
- 硬件:4核8G云服务器,SSD存储
- 软件:EMQX 5.1.0,MySQL 8.0,RocksDB 6.29.5
- 测试工具:emqtt_benchmark,消息大小256B
测试结果
| 存储方案 | 写入TPS | 读取延迟 | 数据可靠性 | 适用场景 |
|---|---|---|---|---|
| Retainer(内存) | 10万+ | <1ms | 节点重启丢失 | 实时状态同步 |
| Durable Storage | 2万-5万 | 5-10ms | 持久化+副本 | 离线消息存储 |
| MySQL(批量写入) | 1万-2万 | 20-50ms | 事务保障 | 业务数据归档 |
| PostgreSQL(规则引擎) | 8千-1.5万 | 30-80ms | SQL事务 | 复杂查询分析 |
关键发现
- 内置存储性能优势:Durable Storage在写入吞吐量上比MySQL高出2-3倍,得益于RocksDB的LSM树结构和批量提交机制
- 外部数据库灵活性:通过规则引擎SQL可实现消息过滤、转换和关联查询,如:
SELECT
payload->>'temperature' as temp,
clientid as device
FROM "#"
WHERE payload->>'temperature' > 30
- 存储成本对比:Durable Storage的磁盘空间利用率比MySQL高40%,因采用列式存储和时间窗口压缩
场景化解决方案
1. 工业设备实时监控
推荐方案:Retainer + Durable Storage组合
- Retainer存储设备最新状态(配置示例)
- Durable Storage保存最近24小时原始数据
- 架构图:
2. 车联网数据平台
推荐方案:Durable Storage + Kafka桥接
- 使用emqx_bridge_kafka将车辆CAN总线数据实时转发至Kafka
- Durable Storage作为故障备份,确保数据零丢失
- 关键配置:
bridge.kafka {
servers = "kafka:9092"
topic = "vehicle_data"
partition_strategy = "round_robin"
compression = "gzip"
}
3. 智能家居数据归档
推荐方案:规则引擎 + PostgreSQL
- 通过emqx_bridge_postgresql实现消息结构化存储
- 利用PostgreSQL的JSONB类型存储半结构化数据
- 数据模型示例:
CREATE TABLE device_events (
id SERIAL PRIMARY KEY,
device_id VARCHAR(64),
event_type VARCHAR(32),
payload JSONB,
timestamp TIMESTAMP DEFAULT NOW()
);
决策指南与最佳实践
存储方案选择流程图
性能优化建议
-
内置存储:
- 调整RocksDB压缩算法:emqx_durable_storage.egress_batch_size
- 合理设置世代滚动周期,避免单个文件过大
-
外部集成:
- 使用批量写入模式,建议批次大小500-1000条
- 为规则引擎添加索引字段,如
clientid和topic
-
监控告警:
- 通过emqx_prometheus监控存储指标
- 关键指标:
emqx_retainer_messages_count、emqx_bridge_mysql_batch_throughput
企业级功能对比
| 功能特性 | 内置存储 | 外部数据库 |
|---|---|---|
| 水平扩展 | 支持Raft集群(emqx_ds_builtin_raft) | 依赖数据库自身扩展能力 |
| 数据备份 | 内置快照机制 | 需单独配置数据库备份 |
| 多租户隔离 | 支持数据库级隔离 | 需通过规则引擎实现 |
| 数据生命周期管理 | 基于时间窗口自动清理 | 需配置数据库定时任务 |
总结与迁移建议
对于大多数物联网场景,推荐优先使用EMQX内置存储方案:
- Retainer适合设备状态同步和配置下发
- Durable Storage适合需要高吞吐、低延迟的消息持久化
当需要长期存储或复杂查询时,可通过规则引擎实现"热数据内置+冷数据外部"的分层存储架构。迁移时建议使用emqx_bridge_mqtt实现双写过渡,确保业务平滑切换。
完整配置示例和性能测试脚本可参考:
- EMQX存储最佳实践
- 规则引擎示例库
选择合适的存储方案,让你的物联网平台在设备规模增长时依然保持稳定高效。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



