Etcd是高可用键值存储,适用于分布式锁等场景;Go客户端必须用clientv3,Watch需循环读取并defer关闭,Put建议配租约实现自动过期。

Go 没有“通用键值存储客户端”模块,必须按后端选具体库——etcd、LevelDB、BoltDB、Redis 各自生态隔离,强行抽象反而增加故障面。
etcd 客户端必须用 clientv3,且 Watch 不能漏 defer
go.etcd.io/etcd/clientv3 是唯一被 etcd 官方维护的 Go 客户端,v2 API 已废弃。常见错误是调用 cli.Watch() 后没处理 resp.Events 的 channel 关闭,或忘记 defer cli.Close() 导致 fd 泄漏。
- 连接必须显式设置
DialTimeout和Username/Password(若开启 auth) -
Watch返回的是clientv3.WatchChan,需在 goroutine 中循环读取,否则阻塞 - Watch key 前缀要用
clientv3.WithPrefix(),不是字符串拼接 - 写操作(
Put)建议加clientv3.WithLease(leaseID)实现自动过期,避免脏数据堆积
LevelDB 只能选 goleveldb 或 levigo,别碰原生 C++ 库
github.com/syndtr/goleveldb/leveldb 是纯 Go 实现,无 CGO;github.com/jmhodges/levigo 是 C binding,性能略高但构建链脆弱。两者 API 不兼容,不能混用。
-
leveldb.OpenFile路径必须是绝对路径,"./db"在容器中大概率失败 - 必须提前确保父目录存在:
os.MkdirAll("/var/lib/myapp/db", 0750),LevelDB 不创建父级 -
opt.Options{ErrorIfMissing: false}是冷启必需项,设为true会导致服务启动失败 - 并发写入时,
Put/Delete本身线程安全,但“读-改-写”逻辑需外部加锁或用 batch 提交,否则竞态
BoltDB 和 badgerDB 都支持嵌入式,但事务模型完全不同
BoltDB 使用单文件 + mmap,只支持单写多读;badgerDB 是 LSM-tree 实现,支持高并发写入。两者都不需要独立进程,但初始化方式差异大。
立即学习“go语言免费学习笔记(深入)”;
- BoltDB 打开即
bolt.Open("path.db", 0600, nil),首次打开会自动建文件;badger 需badger.Open(opt),且opt.Dir和opt.ValueDir必须分开指定 - BoltDB 的
Update是事务入口,所有操作必须包在函数里;badger 的txn := db.NewTransaction(true)需手动txn.Commit()或txn.Discard() - BoltDB 的 bucket 名区分大小写,
db.Bucket([]byte("User"))和db.Bucket([]byte("user"))是两个 bucket - badger 默认启用压缩和内存映射,小数据量下可能比 BoltDB 更耗内存,压测前需关掉
Options{DisableGC: true}
Redis 推荐 redigo 或 go-redis,别用老掉牙的 goburrow/redis
github.com/gomodule/redigo/redis 是连接池 + 原始命令封装,轻量直接;github.com/redis/go-redis/v9 是面向接口设计,支持 pipeline、cluster、sentinel 自动发现,但二进制体积大。
- redigo 必须自己管理
redis.Pool,Get()后记得Close(),否则连接泄漏 - go-redis 的
ctx参数不可省略,超时控制全靠它,rdb.Set(ctx, "key", "val", 0)的0表示永不过期,不是忽略 - 二者都默认不重试失败命令,网络抖动时需自行 wrap
retry.Retry或用redis.Failover结构 - Redis 8.2.3 修复了 CVE-2025-62507,若用 TLS 连接,务必升级 client 并校验
tls.Config.VerifyPeerCertificate
真正麻烦的不是连上某个库,而是不同存储的语义鸿沟:etcd 强一致但无 TTL 原生支持,LevelDB 无 Watch,BoltDB 不支持并发写,Redis 命令丰富但持久化策略要细调。选型时先明确场景——配置中心用 etcd,本地缓存用 badger,简单状态落盘用 BoltDB,高频计数用 Redis。跨存储抽象层往往掩盖问题而非解决问题。


















