您的位置 首页 golang

大规模缓存失效雪崩问题解决方案-golang 解决方案

在一般的接口请求中,一般的获取获取的逻辑为:从memcache或者 redis 中获取 缓存 ,如果缓存失效,则从数据库中获取,这种获取数据的逻辑在qps低的时候也没有什么不良的后果。 但是想象这样的qps较高场景:做活动在最后时刻冲榜单是如果缓存失效,则大量的请求会落到数据库中,很容易就吧数据库打垮,此时上面的获取数据的逻辑就会有问题

解决方案

  1. 定时把数据刷到缓存中,这个对数据规模小且对数据敏感度不高的是一个比较好方案
  2. 在缓存失效获取数据时添加,添加全局锁,这样只读一次数据库,减少并发对数据库的压力,添加锁可以借助memcahe,redis 的incr 等命令来执行

3、可以在各个服务器实例中添加锁,也是一种方法,对并发量不太大的业务也是可行的

栗子-golang

package singleflight
import "sync"
// 一个执行主体
type call struct {
 wg sync.WaitGroup
 val interface{}
 err error
}
type Group struct {
 mu sync.Mutex // protects m
 m map[string]*call // lazily initialized
}
func (g *Group)  Do (key string, fn func() (interface{}, error)) (interface{}, error) {
 g.mu.Lock()
 if g.m ==  nil  {
 g.m = make(map[string]*call)
 }
 // 如果已经有任务存在
 if c, ok := g.m[key]; ok {
 g.mu.Unlock()
 // 等待执行结束
 c.wg.Wait()
 return c.val, c.err
 }
 // 新建一个执行主体
 c := new(call)
 c.wg.Add(1)
 g.m[key] = c
 g.mu.Unlock()
 //获取定义函数的执行接口
 c.val, c.err = fn()
 // 做完任务释放
 c.wg.Done()
 g.mu.Lock()
 // 要删除组
 delete(g.m, key)
 g.mu.Unlock()
 return c.val, c.err
}
注意 do要求的存入的func 为 func() (interface{}, error) 类型
 

文章来源:智云一二三科技

文章标题:大规模缓存失效雪崩问题解决方案-golang 解决方案

文章地址:https://www.zhihuclub.com/97246.shtml

关于作者: 智云科技

热门文章

网站地图