关于go库singleflight的使用问题

问题:并发获取数据的时候超过一个请求访问到数据库了
环境:8核cpu,centos7,go1.14

代码:

package main

import (

"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

回到顶部