golang 防缓存击穿singleflight的实现
作者:xc_oo 时间:2024-05-09 09:55:23
一、什么是缓存击穿
当一个key是热点key时,一般会做缓存来抗大量并发,但当缓存失效的一瞬间,这些大量的并发请求会击穿缓存,直接请求数据库
为了避免缓存击穿,一种解决方法可以设置缓存永不过期,另一种可以使用golang的包 singleflight golang.org/x/sync/singleflight
二、原理
多个并发请求对一个失效key进行数据获取时,只会有其中一个去直接获取数据,其它请求会阻塞等待第一个请求返回给它们结果
三、实现
package singleflight
import (
"sync"
)
var WaitCount int
var DirectCount int
type Caller struct {
val interface{}
err error
wg sync.WaitGroup
}
type Group struct {
mu sync.RWMutex
m map[string]*Caller
}
func (g *Group) Do(key string, fn func() (interface{}, error)) (interface{}, error) {
g.mu.Lock()
if g.m == nil {
g.m = make(map[string]*Caller)
}
c, ok := g.m[key]
if ok {
//阻塞等待其它已经执行此操作的返回结果
g.mu.Unlock()
c.wg.Wait()
WaitCount++
return c.val, c.err
}
//直接请求获取数据
c = &Caller{}
g.m[key] = c
c.wg.Add(1)
g.mu.Unlock()
c.val, c.err = fn()
c.wg.Done()
g.mu.Lock()
delete(g.m, key)
g.mu.Unlock()
DirectCount++
return c.val, c.err
}
测试:
func TestGroup_Do(t *testing.T) {
sg := &Group{}
wg := sync.WaitGroup{}
for i := 0; i < 10000; i++ {
fn := func() (interface{}, error) {
return i, nil
}
wg.Add(1)
go func() {
defer wg.Done()
got, err := sg.Do("test-key", fn)
_, _ = got, err
//t.Log("got:", i)
}()
}
wg.Wait()
fmt.Println("waitCount:", WaitCount)
fmt.Println("DirectCount:", DirectCount)
}
输出:
waitCount: 8323
DirectCount: 1401
来源:https://juejin.cn/post/7012936620177358879
标签:golang,防缓存击穿,singleflight
![](/images/zang.png)
![](/images/jiucuo.png)
猜你喜欢
MySQL与存储过程的相关资料
2024-01-16 03:20:04
Python中itertools模块用法详解
2023-05-28 05:00:27
python pygame实现滚动横版射击游戏城市之战
2021-07-11 00:32:51
![](https://img.aspxhome.com/file/2023/2/83992_0s.jpg)
Python 爬虫学习笔记之多线程爬虫
2022-10-03 15:10:37
![](https://img.aspxhome.com/file/2023/8/95128_0s.png)
js正则表达式验证密码强度【推荐】
2024-04-29 13:39:30
![](https://img.aspxhome.com/file/2023/1/132601_0s.png)
Python实现提取音乐频谱的方法详解
2022-01-27 07:03:08
![](https://img.aspxhome.com/file/2023/2/72072_0s.jpg)
asp中数组的用法
2008-05-12 22:29:00
深入了解Python数据类型之列表
2022-12-21 23:14:15
Python time模块时间获取和转换方法
2022-06-07 11:14:30
Python OpenCV调用摄像头检测人脸并截图
2022-03-19 06:29:02
matplotlib在python上绘制3D散点图实例详解
2022-01-16 03:11:11
![](https://img.aspxhome.com/file/2023/1/115751_0s.png)
asp下查询xml的实现代码
2011-04-19 10:37:00
asp如何用JMail POP3接收电子邮件?
2010-06-13 13:09:00
vue-swiper的使用教程
2024-04-27 16:17:56
Vue常用指令v-if与v-show的区别浅析
2024-05-28 15:46:57
![](https://img.aspxhome.com/file/2023/9/123189_0s.png)
15行Python代码实现免费发送手机短信推送消息功能
2023-11-01 10:20:51
![](https://img.aspxhome.com/file/2023/7/97187_0s.jpg)
认识Javascript数组
2009-08-27 15:26:00
用VBS语言实现的网页计算器源代码
2007-12-26 17:09:00
![](https://img.aspxhome.com/file/UploadPic/200712/26/20071226172731580s.jpg)
Python基于pillow库实现生成图片水印
2021-08-01 10:45:38
python基础编程小实例之计算圆的面积
2023-06-07 06:33:14
![](https://img.aspxhome.com/file/2023/4/99414_0s.png)