版权声明:本文为作者原创,如需转载请通知本人,并标明出处和作者。擅自转载的,保留追究其侵权的权利。golang群:570992072。qq 29185807 个人公众号:月牙寂道长 公众号微信号yueyajidaozhang https://cloud.tencent.com/developer/article/1454568
本文公众号文章链接:https://mp.weixin.qq.com/s/nL6iD6oDcFyuZM-eGSllXg
本文csdn博客文章链接:https://cloud.tencent.com/developer/article/1454568
groupcache是go语言开发的缓存库。用于替换memcache的。
代码目录:
主要的代码框架如下
那么我们一个一个来讲解下。
一、lru
github.com/golang/groupcache/lru/lru.go
Cache结构体里,有两个东西关注下。ll list和cache,用了一个map来做查找,用ll来做lru刷新。
二、consistenthash
github.com/golang/groupcache/consistenthash/consistenthash.go
一致性hash,这里的代码也是很简单的。想要了解的,可以先去看看一致性hash原理
三、singleflight
github.com/golang/groupcache/singleflight/singleflight.go
这个文件里的代码很少,但很重要
Group结构体里,包含了一个map,value是call,其中包含了一个wg。这个wg是重点
这里面用了waitgroup来实现并发写的拦截,合并成一个写。
这个才是这个代码的重要之处。
先上锁,从map中查找key锁对应的wg,没找到则new一个wg。找到了则,wg.wait等待
然后解锁,进行回调函数(这里一般为写操作),也就是合并操作。
操作完,则调用wg.done表示操作完成。并从map中将此次key的删除掉。
那些并发wg.wait的操作,这个时候则会等到操作完的信号。
四、byteview sinks
github.com/golang/groupcache/byteview.go
这个代码里面封装了一个数据结构
github.com/golang/groupcache/sinks.go
而这个里面则封装了sink这个接口。然后基于ByteView,又封装了很多sink接口的数据结构。
五、groupcachepb
github.com/golang/groupcache/groupcachepb/groupcache.pb.go
这个是自动生成的代码,protobuf协议,用于http数据传输用的。
六、http
github.com/golang/groupcache/http.go
http的话,就分为两个部分。http server部分,还有一个部分则是分布式peer部分。
先看结构体
最重要的几个为:
HTTPPool.peers 分布式的peers
HTTPPool.httpGetters 分布式的peer得get接口 httpGetter
HTTPPoolOptions.HashFn 一致性hash的hash方法
先看下初始化,初始化后,调用了http.Handle,这个是标准库net/http的Handle。看到这里就知道在注册路由了。路由路径为opts.BasePath,对应的路由处理则为p。
这里有三个重要的东西
BashPath,默认为/_groupcache/
peers,利用一致性hash初始化
注册了PeerPicker,这个是http模块通过peers.go中的接口来与groupcache连接的部分
我们看下httpGetter结构体
看下红色框中的,baseURL,这个就是后面Get的url
再看看注册接口,通过key通过一致性hash查找到peer,然后返回了分布式peer的接口
从分布式peer部分获取cache
先构造了url,由peer的basePath,加上group name再加上key。构造Get获取
最后写入out中
再有就是http server部分。这个为本地向外提供访问接口部分
先讲path进行分割,获取到groupname,key。
然后通过groupcache获取到key对应的value。
最后通过pb编码发送出去。
网络这块就完结了
七、peers接口
github.com/golang/groupcache/peers.go
这个文件里的代码,则为groupcache与http直接的接口部分
这个就是接口
注册接口,这个在http部分已经讲过了
getPeers则为即将要讲解的groupcache部分需要用到的函数。
八、groupcache
github.com/golang/groupcache/groupcache.go
那么一步一步来
Getter为用户需要注册给groupcache的部分,当没有被缓存的时候,需要到原始地方获取value的函数。
Group结构体,解释下重要的部分
getter为用户注册的原始get部分
peers则为与http部分进行联结的接口
maincache为分布式中本地分配到的cache部分
hotcache为分布式中非本地的被本地访问过的cache部分
loadGroup则为fiightGroup是一个合并操作的部分
初始化很简单。有一个loadGroup初始化为了上面介绍过的合并操作。
Get的是,先查找lookupCache,查找不到会load
继续跟踪
先从maincache中查找,再从hotcache中查找。
查找不到则继续load
这里就是合并操作
这里有个double check的概念,又重新lookupcache一次。
查找不到,则获取peer(peers.pickpeer),通过分布式网络获取(getFromPeer)
如果还找不到则getlocally。
最后有一个popilatecache操作。
流程是全部结束了。
继续看下细节部分
从peer获取Get
用户注册的原始获取部分
这里是刷新缓存部分,当缓存超过容量,则刷新掉old cache。
龚浩华
月牙寂道长
QQ 29185807
2018年03月27日