Go 中使用 singleflight 防止缓存击穿
一个典型的使用缓存的案例:
// GetConfig 获取 key 指定的配置项
func GetConfig(key string) (Config, bool)
但这样存在一个问题: 如果 300 秒缓存过期时,有大量并发产生,将会导致这些并发在缓存中都找不到数据去查数据库的情况,从而发生所谓的缓存击穿。
我们可以使用 golang.org/x/sync/singleflight 来解决这个问题, singleflight 中主要是一个 Group 结构体,它包含以下三个函数:
// Do 执行并返回函数 fn 的结果,并确保在相同 key 在并发调用执行时,只会有一个调用被真正执行,
// 其它重复调用将会直接使用第一个执行的结果返回
// 返回的第 3 个参数 shared 表示返回的结果是直接执行得到的还是其它并发调用共享的。
func (key string, fn func() (interface, error)) (v interface, err error, shared bool)
// DoChan Do 的 channel 返回值形式(异步)
func (key string, fn func() (interface, error)) <-chan Result
// Forget 用于删除指定 key,删除后其它并发调用者将会被真正执行
func (key string)
将 GetConfig() 重命名为 doGetConfig(),然后重新写一个 GetConfig() 函数:
var sg *singleflight.Group
func init()
// GetConfig 获取 key 指定的配置项
func GetConfig(key string) (Config, bool)