3. 本地存储技术选型:SQLite、RocksDB、LevelDB 的对比与选型策略
边缘计算里,存储选型是个绕不开的坎儿。
我见过不少团队,一上来就上 MySQL,结果边缘设备那点资源根本扛不住。也见过有人图省事全用文件存,最后查询慢到怀疑人生。
说白了,边缘存储没有银弹。SQLite、RocksDB、LevelDB 这三兄弟,各有各的脾气。今天我就把它们的底裤扒干净,告诉你什么场景该选谁。
核心结论先放这:
- 需要 SQL 查询、数据结构简单、单机写入不频繁 → SQLite
- 需要高吞吐写入、Key-Value 场景、数据量大 → RocksDB
- 资源极度受限、纯嵌入式、写入量中等 → LevelDB
3.1 SQLite:边缘界的"瑞士军刀"
SQLite 是我个人用得最多的边缘存储方案。为什么?因为它太省心了。
你想想看,一个几百 KB 的库文件,就能跑完整的 SQL 引擎。不需要单独部署服务,不需要配置账号密码,你的程序直接调 API 就行。
适合的场景:
- 设备配置信息管理(比如网关的规则表)
- 日志结构化存储(需要按时间、级别查询)
- 小规模数据的关系查询(几百 MB 以内)
但要注意它的短板:
- 写入并发差。默认是串行写入,多线程同时写会锁库
- 数据量超过 2GB 后性能下降明显
- 不支持主从复制,数据冗余得自己想办法
我的经验: 在工业网关项目里,我用 SQLite 存设备配置和告警记录。单设备每天产生约 50MB 数据,保留 7 天,完全够用。但千万别拿它当时序数据库用——写入一上去就崩。
3.2 RocksDB:写入狂魔,LSM-Tree 的代言人
RocksDB 是 Facebook 从 LevelDB fork 出来的增强版。说白了,它就是为"写多读少"的场景量身定做的。
核心优势:
- 写入吞吐极高,单机每秒几十万次写入很轻松
- 支持列族(Column Family),可以逻辑上分表
- 内置压缩、Bloom Filter、缓存等优化
- 支持多线程 compaction,后台合并效率高
代价是什么?
- 读性能不如 B+Tree,尤其是随机读
- 内存占用偏高,默认配置下 1GB 数据可能吃掉 200MB 内存
- 编译依赖多,交叉编译到 ARM 平台有点折腾
我曾经踩过的坑: 在一个视频分析边缘盒子里,我用 RocksDB 存特征向量和元数据。一开始没调 compaction 参数,结果后台合并线程把 CPU 吃满了,视频处理帧率直接掉到 10fps。后来把 max_background_compactions 从 4 降到 1,才稳住。
3.3 LevelDB:轻量级的老前辈
LevelDB 是 Google 出品的老牌 LSM-Tree 实现。RocksDB 就是基于它改的。
现在纯用 LevelDB 的场景不多了,但有些极端资源受限的设备还是得靠它。
它比 RocksDB 好在哪?
- 代码量小,编译后体积只有几百 KB
- 内存占用低,适合只有 32MB/64MB RAM 的设备
- API 简单,学习成本几乎为零
缺点也很明显:
- 单线程 compaction,写入量大了容易卡住
- 没有列族,所有数据挤在一个命名空间
- 不支持事务,没有 WAL 的原子性保证
我的建议: 除非你的设备 RAM 低于 64MB,否则直接上 RocksDB 吧。LevelDB 已经停止活跃开发了,社区支持也弱。我手头有个温湿度传感器节点,用 STM32 + LevelDB 存一周的数据,勉强能跑——但但凡内存多 32MB,我都会换成 RocksDB。
3.4 三者的核心对比
| 维度 | SQLite | RocksDB | LevelDB |
|---|---|---|---|
| 数据模型 | 关系型(SQL) | Key-Value | Key-Value |
| 写入性能 | 中等(串行写入) | 极高(LSM-Tree) | 高(但单线程 compaction) |
| 读取性能 | 高(B+Tree) | 中等(需查多层) | 中等 |
| 内存占用 | 低(几十 MB) | 中高(200MB+) | 极低(几十 MB) |
| 事务支持 | 完整 ACID | 单行原子性 | 无 |
| 并发写入 | 差(写锁) | 好(多线程) | 一般 |
| 编译难度 | 极低(Amalgamation) | 中(依赖多) | 低 |
| 典型场景 | 配置管理、小规模日志 | 时序数据、特征存储 | 极端资源受限设备 |
3.5 选型决策流程
我一般按这个思路来选,你可以参考一下:
- 需要 SQL 查询吗? 是 → SQLite。不是 → 下一步。
- 写入量超过 1000 ops/s? 是 → RocksDB。不是 → 下一步。
- 设备 RAM 小于 64MB? 是 → LevelDB。不是 → RocksDB。
- 需要事务和 ACID? 是 → SQLite。不是 → RocksDB。
一个真实案例: 去年我做智能电表边缘网关,ARM Cortex-A7,512MB RAM,每天产生约 200 万条用电记录。我选了 RocksDB,按小时分列族存储。查询时按时间范围扫列族,配合 Bloom Filter,单次查询平均 3ms。如果当时用 SQLite,写入就卡死了。
3.6 核心知识体系
下面这张图总结了本章的选型逻辑,你可以保存下来当参考:
3.7 避坑指南
最后分享几个我亲手踩过的坑,你遇到了能少走弯路:
- 别在 SQLite 上做高并发写入。 我曾经用 8 个线程同时写同一个 SQLite 库,结果 5 分钟后数据库就报 "database is locked"。后来改成单线程队列写入,问题解决。
- RocksDB 的 compaction 要调参。 默认配置是为服务器设计的,边缘设备 CPU 弱,一定要限制后台线程数。我一般设 max_background_jobs = 1 或 2。
- LevelDB 的读放大问题。 数据量超过 1GB 后,一次读取可能要查 5-6 层 SST 文件。建议配合 Bloom Filter 使用,能减少 90% 的无用 IO。
- 别忘了 WAL。 边缘设备经常意外断电。RocksDB 和 SQLite 默认都写 WAL,但 LevelDB 需要手动开启。不写 WAL,断电丢数据是必然的。
一句话总结: 能上 SQLite 就上 SQLite,它最省心。写入量大就上 RocksDB,但要舍得给它内存。只有资源实在不够了,才考虑 LevelDB。
公众号:蓝海资料掘金营,微信deep3321