什么是缓存击穿?原理及实现是什么
Admin 2022-08-13 群英技术资讯 880 次浏览
一、什么是缓存击穿
当一个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
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
关于设计模式,我们可以理解为是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。PHP设计模式有单例模式、注册模式、策略模式等等,文本主要给大家介绍的策略模式。
今天在做登陆认证时遇到了个问题,以为是我的解决方法,希望对大家有所帮助吧
一个数组中的值可以是另一个数组,另一个数组的值也可以是一个数组。依照这种方式,我们可以创建二维或者三维数组。下文有实例供大家参考,对大家了解操作过程或相关知识有一定的帮助,而且实用性强,希望这篇文章能帮助大家,下面我们一起来了解看看吧。
Cookie与Session一般认为是两个独立的东西,Session采用的是在服务器端保持状态的方案,而Cookie采用的是在客户端保持状态的方案。Cookie分为两种,一种可以叫做session...
php中PDO获取关联数组:1、可以使用 PDO::FETCH_ASSOC 来获取关联数组。2、创建一个$options组,将所有默认配置放入其中,只需将数组传递到$conn变量。
成为群英会员,开启智能安全云计算之旅
立即注册Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008