groupcache源码分析(singleflight防缓存击穿)

Posted 会跳舞的哈密瓜

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了groupcache源码分析(singleflight防缓存击穿)相关的知识,希望对你有一定的参考价值。

groupcache源码分析(singleflight)

主要的功能是抑制同一个函数调用重复执行,也就是说,如果对于某个key的请求已经存在并且正在进行,则对该key的新的请求会堵塞在这里,等原来的请求结束后,将请求得到的结果同时返回给堵塞中的请求。可以达到防止缓存击穿的效果。

//在执行的或者已经完成的do过程,实际请求函数的封装
type call struct 
	wg  sync.WaitGroup
	val interface
	err error


//主要是用来阻止对已经存在的某key的请求和对应的实际请求函数映射
type Group struct 
	mu sync.Mutex       // protects m
	m  map[string]*call // lazily initialized

//Do接收一个函数,执行并返回结果,这个过程中确保同一个key在同一时间只有一个执行过程;重复的调用会等待最原始的调用过程完成,然后接收到相同的结果
func (g *Group) Do(key string, fn func() (interface, error)) (interface, error) 
	g.mu.Lock()   // 有可能要修改m,所以要先上锁保护
	if g.m == nil   //如果m为nil则初始化
		g.m = make(map[string]*call)
	
  //如果m中存在对key的请求,所以该线程不会再次访问key,释放锁。然后阻塞进程等待已经存在的请求得到的结果
	if c, ok := g.m[key]; ok 
		g.mu.Unlock()
		c.wg.Wait()  // 阻塞,直到计数器变为0,代表已经存在的请求完成
		return c.val, c.err
	
  // 如果不存在对该key的请求,则本线程要进行实际的请求,保持m的锁定状态
	c := new(call)  // 创建一个实际请求实体
	c.wg.Add(1)  // 将计数器加1,保证其他的相同请求保持阻塞状态
	g.m[key] = c 
	g.mu.Unlock()  // 解锁

  // 执行真正的请求函数,得到对该key的请求结果
	c.val, c.err = fn()
	c.wg.Done() // 得到结果后将其他请求该key的线程移除阻塞状态

  // 请求完成后,要从已经存在请求的map中删除
	g.mu.Lock()
	delete(g.m, key)
	g.mu.Unlock()

  //返回结果
	return c.val, c.err

以上是关于groupcache源码分析(singleflight防缓存击穿)的主要内容,如果未能解决你的问题,请参考以下文章

groupcache源码分析(singleflight防缓存击穿)

groupcache源码分析(singleflight防缓存击穿)

groupcache源码分析(singleflight防缓存击穿)

源码分析之groupcache之consistenthash

groupcache源码解析-概览

groupcache源码解析(IRU)