关于go库singleflight的使用问题
问题:并发获取数据的时候超过一个请求访问到数据库了
环境:8核cpu,centos7,go1.14
代码:
package mainimport (
"errors"
"log"
"sync"
"golang.org/x/sync/singleflight"
)
var errorNotExist = errors.New("not exist")
var g singleflight.Group
func main() {
var wg sync.WaitGroup
cpu_amount := 4
wg.Add(cpu_amount)
for i := 0; i < cpu_amount; i++ {
go func() {
defer wg.Done()
data, err := getData("key")
if err != nil {
log.Print(err)
return
}
log.Println(data)
}()
}
wg.Wait()
}
func getData(key string) (string, error) {
data, err := getDataFromCache(key)
if err == errorNotExist {
v, err, _ := g.Do(key, func() (interface{}, error) {
return getDataFromDB(key)
})
if err != nil {
log.Println(err)
return "", err
}
data = v.(string)
} else if err != nil {
return "", err
}
return data, nil
}
func getDataFromCache(key string) (string, error) {
return "", errorNotExist
}
func getDataFromDB(key string) (string, error) {
log.Printf("get %s from database", key)
return "data", nil
}
执行结果1:
执行结果2:
执行结果3:
回答
singleflight 只是避免“同时”高并发的访问,也就是说,只有4个协程都在运行的时候,才满足“同时”的条件。
你看看 singleflight 的例子就明白了,例子里面都有一句
time.Sleep(time.Millisecond * 500)
why? 这就保证所有启动的协程都在同时运行。
而你的 getDataFromDB,输出一条信息后就结束了,也就是说如果前面三个协程都执行完了,第四个来执行了,当然就没有“同时”性了,也不会导致访问击穿,就会进入到 Do 里面去执行。
以上是 关于go库singleflight的使用问题 的全部内容, 来源链接: utcz.com/a/23192.html