能跑通,但默认配置下极易丢数据、panic或启动失败——关键在初始化需显式设Dir和ValueDir、写操作必须用db.Update封装、读取须ValueCopy、关闭前必须调db.Close()且不能重复。

直接说结论:Gin 做 HTTP 层,Badger 做本地持久层,能跑通,但默认配置下极易丢数据、panic 或启动失败——关键在初始化、事务用法和生命周期管理这三处。
badger.Open() 必须显式设 Dir 和 ValueDir
Badger 不像 Bolt 那样传一个路径就能开库。它把索引(Dir)和值(ValueDir)分开存,两者路径可以相同,但都必须显式赋值。否则:badger.Open(badger.DefaultOptions("./data")) 看似正常,实则 ValueDir 会退化为临时目录,进程一退出,所有 value 全丢。
正确写法是:
opts := badger.DefaultOptions("./data")
opts.ValueDir = "./data"
db, err := badger.Open(opts)常见错误:
- 只传空字符串或
""→ 创建临时目录,数据不落盘 - 用相对路径如
"data"→ 在不同工作目录下行为不一致,建议统一用"./data" - 两个路径指向不同磁盘 → 可能因 IO 延迟放大写延迟,非必要不这么做
写操作必须用 db.Update,读操作优先用 db.View
db.Update 是唯一安全的写入口,它自动开启写事务(txn := db.NewTransaction(true)),并保证 Commit() 或 Discard()。漏掉这层封装,直接调 txn.Set() 而没 Commit(),数据就卡在内存里,重启即消失。
db.View 是只读快照,不阻塞写,适合高频查询场景。但它不保证看到最新写入——因为底层是 snapshot 机制,Update 提交后,正在执行的 View 还可能读到旧值。
容易踩的坑:
- 在
View函数里调db.Update→ 直接 panic “recursive txn” - 把网络请求、JSON 解析等耗时逻辑塞进
Update函数体 → 持有写锁太久,后续所有读写全排队 - 用
txn.Get().Value()后再访问该切片 → 事务结束,内存被复用,结果是脏数据或 panic;必须用item.ValueCopy(nil)
db.Close() 不是可选项,是强制关机步骤
Badger 用 mmap 和后台 goroutine 管理文件,不调 db.Close() 就退出进程,value log 文件极大概率损坏。下次启动报错类似:"manifest has unsupported version" 或 "checksum mismatch",不是版本问题,是文件已坏。
实操要点:
- 务必在
main()结束前、或收到SIGINT/SIGTERM信号时调用db.Close() - 不能重复调用
Close(),否则 panic - Gin 启动后,
defer db.Close()无效——因为 Gin 的router.Run()是阻塞的,defer永远不会执行。得用signal.Notify捕获退出信号 - 若需 crash-safe,打开时设
opts.SyncWrites = true,但写吞吐会降 15–30%
ValueLog 空间不回收,必须手动 GC
Badger 删除 key 后,对应的 value 仍留在 value.log 文件里,不会自动清理。长期运行后磁盘占满是常态,不是 bug。
解决方案只有定期触发 GC:
go func() {
ticker := time.NewTicker(2 * time.Hour)
defer ticker.Stop()
for range ticker.C {
if err := db.RunValueLogGC(0.7); err == nil {
log.Println("ValueLog GC done")
}
}
}()注意:
-
RunValueLogGC会阻塞写入,别在高峰期跑 - 参数
0.7表示当 70% 的 value 空间无效时才触发,太低(如 0.3)会导致 GC 过于频繁 - 如果 value 普遍 > 1KB,建议把
opts.ValueLogFileSize从默认 1GB 改成 256MB,加快单次 GC 效率
最常被忽略的一点:Badger 的“本地 KV”定位很明确——它不支持跨 key 事务、没有二级索引、也不做自动压缩。把它当 Redis 用,或者指望它替代 PostgreSQL 的某个表,都会在中后期撞墙。它真正擅长的,是高吞吐写入小 key + 大 value 的场景,比如权限缓存快照、用户会话元数据、配置变更日志。


















