配置文件适合用LRU缓存,因其读多写少、结构稳定、解析开销大,LRU可避免重复解析;应缓存解析后的结构体指针(如lru.New[string, *Config]),而非原始字节,并通过Remove()精准热更新,同时确保结构体不含非序列化字段以防内存泄漏。

直接读配置文件再解析,比用 lru 缓存快不了多少,反而可能更慢——因为每次都要打开文件、IO、反序列化;真正省时间的是跳过这些步骤,把解析结果缓存住。
为什么配置文件适合用 LRU 缓存?
配置通常读多写少、结构稳定、变更频率低(比如启动时加载或热重载),且解析开销明显(YAML/JSON 解析、字段校验、嵌套结构展开)。LRU 不是为它设计的“淘汰场景”,但能有效避免重复解析。
- 配置键名固定(如
"db.timeout"、"feature.flag"),天然适配键值缓存 - 不需要 TTL,但需支持热更新后手动
Purge()或按版本号Remove() - 并发读频繁,写极少——
golang-lru/v2的读写锁实现刚好匹配
怎么缓存解析后的结构体,而不是原始字节?
别缓存 []byte 或 string,直接缓存解析后的结构体指针。否则每次 Get() 后还得再解一次,白搭。
- 定义配置结构体:
type Config struct { DBTimeout int `json:"db_timeout"` } - 缓存类型声明为:
lru.New[string, *Config],不是lru.New[string, []byte] - 首次加载时解析一次,存指针:
cache.Add("config_v1", &cfg) - 后续
Get()返回的就是可直接用的*Config,零额外开销
热重载时怎么安全刷新缓存?
用 Remove() 比 Purge() 更精准,避免误清其他业务缓存。
立即学习“go语言免费学习笔记(深入)”;
- 监听配置文件
fsnotify事件,触发重加载 - 新配置解析成功后,先
cache.Remove("config"),再Add("config", newCfgPtr) - 不要在回调里直接
Purge()——你很可能还缓存了用户 session、API schema 等其他东西 - 如果多个配置文件共用一个 cache 实例,建议加前缀:
"config:db"、"config:feature"
容易被忽略的内存泄漏点
结构体里含 sync.Mutex、http.Client、io.Closer 等非序列化字段时,缓存指针会阻止 GC 回收底层资源。
- 确保配置结构体只含纯数据字段(int/string/map/slice),不含运行时对象
- 若必须带初始化资源(如 DB 连接池),应单独管理,不放进缓存结构体
- 检查
unsafe.Sizeof(*Config)是否异常大——可能是意外嵌套了大对象


















