• 初探groupcache


    groupcache是用于dl.google.com的一个memcached的替代品,相对于memcached,提供更小的功能集和更高的效率,以第三方库的形式提供服务。

    groupcache的常见部署可参考下图:

    不同于memcached,groupcache面向的是静态的缓存系统,比如google家的下载站,用来缓存对应的文件区块。一经set操作,key对应的value就不再变化。使用的时候,需要自定义缓存缺失时使用的set操作。当发生miss的时候,首先会从根据key的consist hash值找到对应的peer,去peer里寻找对应的value。如果找不到,则使用自定义的get函数从慢缓存(比如db,文件读取)获取alue,并填充对应peer。下一次获取,就直接从cache里取出来,不再访问慢缓存。另外,为避免网络变成瓶颈,本地peer获取cache后,会存在本地的localCache里,通过LRU算法进行管理。

    groupcache的代码分为consistenhash, groupcachepb, lru, singleflight等几个目录,分别存放一致性哈希,groupcache的protobuf协议,lru算法实现,用来保证求值操作只执行一次的singleflight。本篇主要看看singleflight。

    23 // call is an in-flight or completed Do call
    24 type call struct {
    25 wg sync.WaitGroup
    26 val interface{}
    27 err error
    28 }

    这里定义了一个call结构,包含了用来同步的wg等待组,一个用于承载任意值的val,以及err错误信息。

    32 type Group struct {
    33 mu sync.Mutex // protects m
    34 m map[string]*call // lazily initialized
    35 }

    这里定义的是Group结构,一个Group内key是唯一的,类似于命名空间。groupcache使用了Mutex保护map变量。

    41 func (g *Group) Do(key string, fn func() (interface{}, error)) (interface{}, error) {
    42 g.mu.Lock()
    43 if g.m == nil {
    44 g.m = make(map[string]*call)
    45 }
    46 if c, ok := g.m[key]; ok {
    47 g.mu.Unlock()
    48 c.wg.Wait()
    49 return c.val, c.err
    50 }
    51 c := new(call)
    52 c.wg.Add(1)
    53 g.m[key] = c
    54 g.mu.Unlock()
    55
    56 c.val, c.err = fn()
    57 c.wg.Done()
    58
    59 g.mu.Lock()
    60 delete(g.m, key)
    61 g.mu.Unlock()
    62
    63 return c.val, c.err
    64 }

    这里Do定义的就是一个带锁保护的保证单次执行的函数。因为consistent hash定位到的peer是唯一的,因此这里只需要同步该进程内的goroutine即可。为了减少锁的影响,锁控制的范围被切成了好几段。整个完整流程包括3步:1. 初始化g.m变量 2. 赋值g.m[key]变量为val 3.删除g.m的key。第一步会加锁,第一个进入的go程会走到第二步进行赋值操作,到其他go程进入1的时候,第二步key对应的值已经有了,可以直接释放锁了。然后到第三步,第一个进入的go程会加锁,然后删除key,再解锁。前面尽早释放锁,就是为了第三步这里不需要长久的等待。

  • 相关阅读:
    剑指 Offer 55. 二叉树的深度
    剑指 Offer 11. 旋转数组的最小数字
    [COCOS2DX-LUA]0-006.cocos2dx中关于拖动屏幕物件,同时点击home键,返回后页面变黑的问题。
    Kafka 入门(三)--为什么 Kafka 依赖 ZooKeeper?
    Kafka 入门(二)--数据日志、副本机制和消费策略
    Kafka 入门(一)--安装配置和 kafka-python 调用
    网络通信基础笔记
    项目经理的必要性
    Jenkins用户管理
    JVM笔记二双亲委派机制
  • 原文地址:https://www.cnblogs.com/Lifehacker/p/groupcache_inside.html
Copyright © 2020-2023  润新知