没用singleflight之前
package main
import (
"fmt"
"sync"
"time"
)
var (
mx sync.Mutex
wg sync.WaitGroup
cacheData = make(map[string]string, 0)
)
func main() {
// 添加10个任务,模拟并发请求
wg.Add(10)
for i := 0; i < 10; i++ {
go getData("demo")
}
// 等待所有任务完成
wg.Wait()
}
func getData(key string) {
data, _ := getDataFromCache(key)
if len(data) == 0 {
// 缓存没有找到,则进行回源
data, _ = getDataFromDB(key)
// 设置缓存
mx.Lock()
cacheData[key] = data
mx.Unlock()
}
fmt.Println(data)
// 任务完成
wg.Done()
}
func getDataFromCache(key string) (string, error) {
return cacheData[key], nil
}
func getDataFromDB(key string) (string, error) {
fmt.Println("getDataFromDB key: ", key)
// 模拟访问db的耗时
time.Sleep(10 * time.Millisecond)
return "db data", nil
}
输出
getDataFromDB key: demo
getDataFromDB key: demo
getDataFromDB key: demo
getDataFromDB key: demo
getDataFromDB key: demo
getDataFromDB key: demo
getDataFromDB key: demo
getDataFromDB key: demo
getDataFromDB key: demo
getDataFromDB key: demo
db data
db data
db data
db data
db data
db data
db data
db data
db data
db data
使用
package main
import (
"fmt"
"golang.org/x/sync/singleflight"
"sync"
"time"
)
var (
mx sync.Mutex
wg sync.WaitGroup
g singleflight.Group
cacheData = make(map[string]string, 0)
)
func main() {
// 添加10个任务
wg.Add(10)
for i := 0; i < 10; i++ {
go getDataSingleWarp("demo")
}
// 等待所有任务完成
wg.Wait()
}
func getDataSingleWarp(key string) {
data, _ := getDataFromCache(key)
if len(data) == 0 {
// 使用singleflight来避免并发请求,实际改动就这一行
d, _, shared := g.Do(key, func() (interface{}, error) {
return getDataFromDB(key)
})
fmt.Println(shared)
data = d.(string)
// 设置缓存
mx.Lock()
cacheData[key] = data
mx.Unlock()
}
fmt.Println(data)
wg.Done()
}
func getDataFromCache(key string) (string, error) {
return cacheData[key], nil
}
func getDataFromDB(key string) (string, error) {
fmt.Println("getDataFromDB key: ", key)
// 模拟访问db的耗时
time.Sleep(10 * time.Millisecond)
return "db data", nil
}
输出
getDataFromDB key: demo
true
db data
true
db data
true
db data
true
db data
true
db data
true
db data
true
db data
true
db data
true
db data
true
db data