badgerdb必须显式调用db.close()才能保证数据持久化,否则进程退出时因valuelog异步刷盘机制可能导致数据丢失;开发调试可临时用db.sync(),生产环境须用defer或信号捕获确保close执行。

BadgerDB 能直接用作本地 KV 存储,但必须显式调用 DB.Close(),否则进程退出时数据可能丢失——这是最常被忽略的致命点。
为什么 BadgerDB 写入后查不到?
默认开启 ValueLog 的异步刷盘机制,Set() 返回成功不等于已落盘。若未调用 DB.Sync() 或未等 DB.Close() 完成,重启后数据消失。
- 开发调试时,每次写完立刻调用
db.Sync()(仅限小数据量,影响性能) - 生产环境务必在进程退出前执行
db.Close(),且需用defer或os.Interrupt信号捕获确保执行 - 避免在
Set()后立即Get()就认为“已持久化”——Get()读的是内存索引+ValueLog缓存,和落盘无关
如何安全地打开和关闭 BadgerDB 实例?
BadgerDB 不支持多进程并发访问同一目录,且 Open() 失败时不会自动清理锁文件,残留 LOCK 文件会导致后续启动卡死。
- 打开时传入
Options{Dir: "./data", ValueDir: "./data"},两个路径必须一致或显式分离;若只设Dir,ValueDir默认同值 - 首次启动失败(如权限不足、磁盘满),手动删掉
./data/LOCK再试,Badger 不会自动覆盖损坏锁 - 关闭必须用
defer db.Close(),且不能放在 goroutine 中——Close()是同步阻塞操作,需等待所有 pending write 完成
Key 和 Value 有哪些实际限制?
Badger 对 Key 长度无硬性上限,但超过 64KB 会显著拖慢 LSM tree 合并;Value 存在 ValueLog 分片限制,默认单条最大 1MB,超限会 panic。
- Key 建议控制在 1–2KB 内,过长会影响内存索引效率和 SSTable 过滤器精度
- Value 超过 1MB 必须手动分片或改用外部存储(如文件系统),Badger 不自动拆分
- Value 不能是 nil,空值请用
[]byte{};Key 也不能为 nil,否则Set()panic - 不支持嵌套事务跨 goroutine,
DB.NewTransaction(true)的只读事务可并发,但写事务必须串行
ValueLog 的 GC 和 compaction 是后台异步运行的,观察 db.RunValueLogGC(0.7) 是否频繁触发能判断 Value 是否长期未被覆盖——这直接影响磁盘空间回收速度,容易被当成“磁盘越用越大无法释放”。











