您的位置:首页 > 编程语言 > Go语言

groupcache源码阅读笔记

2015-07-28 17:45 507 查看

groupcache简介

已发布至个人博客,地址在这里

groupcache是大神Brad Fitzpatrick使用golang开发的一个缓存系统。代码地址在这里。可以作为memcache的替代品存在。不过两者也是有不同的,groupcache既是客户端也是服务器,也就是说它是作为一个库存在的,跟业务代码共生,这样的好处就是,部署简单,谁用谁知道。

我在刚开始看代码的时候,grep了半天main,什么都没找到,囧,希望大家先理解这一点。

groupcache的代码结构包括下面几部分:



consistenthash一致性hash,其作用参见这里,在groupcache里,其用来决定key存放在哪个实例里面。

groupcachepb protobuffer的源码在这里,在groupcache中,同一个group中的多个实例交互数据,使用pb,减少数据体积。

lru 这里是最终存数据的地方,里面使用了两种数据结构,map和list,map用来保存key-value数据,list按访问顺序保存value,这样实现lru,在清理数据的时候,将最久未访问的数据清除掉。

singleflight 用来控制调用只被执行一次。在这里用来控制,当数据在本地缓存中不存在时,不会都将请求发到数据库或者其他的实例中,以此来避免”惊群”。实现还是很巧妙的,而且这种方案在golang本身的代码中也有采用,如果你的业务中有类似需求,也可以借鉴此处的代码。

btyeview.go 这个可以理解为一种数据格式,在groupcache中,将所有的value都保存为byteview的格式。优先使用[]byte表示,否则使用string。

groupcache.go 这是groupcache的核心,这里定义了groupcache的核心数据结构—group,以及围绕group的get等核心操作。

http.go 这里是业务和groupcache交互的接口

peers.go 同一个group里可以有多个节点,peers是用来表示这种关系的

sinks.go 这个东西用来接收Get到的数据

Get之旅

下面描述一次Get请求在groupcache里经过的历程。代码在groupcache.go中。

首先Group会去初始化它的peers节点,但是又不能每次get的时候都去调用,所以这里采用了sync.once用来保证只执行一次。

将GETS状态+1,跟我们在memcache中看到的各种统计信息一样,用来统计Cache Get, Cache Miss

从当前节点获取缓存内容,从mainCache中获取,如果没有从hotCache中获取。

如果当前节点没有获取到结果,则会从peers的节点中获取内容,如果没有,则会从用户定义的getter方法中获取信息(此时会使用singleflight,来保证只有1个请求会真正发起请求,也就是,如果对当前节点有5个对key=test的请求,则只有1个会真正向peers发起请求,而其他四个请求会block,直到请求返回。而且先从peers请求,再从getter中获取也是有讲究的,因为,如果在3台业务机上同时对key=test发起请求,那么会保证只会调用一次getter,从而避免memcache等缓存的业务冷启动问题)

将获取的结果返回

func (g *Group) Get(ctx Context, key string, dest Sink) error {
g.peersOnce.Do(g.initPeers)  // 1
g.Stats.Gets.Add(1) // 2
if dest == nil {
return errors.New("groupcache: nil dest Sink")
}
value, cacheHit := g.lookupCache(key) //

if cacheHit {
g.Stats.CacheHits.Add(1)
return setSinkView(dest, value)
}

// Optimization to avoid double unmarshalling or copying: keep
// track of whether the dest was already populated. One caller
// (if local) will set this; the losers will not. The common
// case will likely be one caller.
destPopulated := false
value, destPopulated, err := g.load(ctx, key, dest)
if err != nil {
return err
}
if destPopulated {
return nil
}
return setSinkView(dest, value)
}


groupcache的一种部署架构

groupcache的一种部署架构

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  groupcache golang