本文是研究Groupcache的第一篇,简单跑个Groupcache的例子,对一些代码进行简要分析。
示例 & 运行
示例代码如下:
|
|
这段代码补全自:https://talks.golang.org/2013/oscon-dl.slide#45
运行步骤:
- 本人先在工程目录下放上一张帅气的自拍,文件名为big-file.jpg,运行程序后服务器启动,在浏览器输入 http://localhost:8080/thumbnails/big-file.jpg 后,帅气光芒迸发;
- 将帅气自拍从本地删除,另起一个server,该server监控8081端口,在浏览器输入 http://localhost:8081/thumbnails/big-file.jpg ,虽然本地并不存在big-file.jpg,但是由于自拍已然缓存,所以帅气光芒依旧迸发;
代码简单分析
将目光聚焦到路由函数HandleFunc()中,可以看到关键的处理函数是Get(),通过它,data最终将获得被写入的值(缓存和本地都不能得到值将打印错误)。
走进Get()内部:
|
|
ctx是一个opaque值,通常可以设为nil;dest是一个Sink,Sink作为一个接口集合了一些数据处理的方法。在这里代码传入了一个groupcache.AllocatingByteSliceSink(&data)方法,该方法返回的是一个实现了Sink接口方法的结构体实例,结构体长这样:
|
|
所以dest就是该结构体实例,实例的dst字段指向传入的data,Get函数会调用g.lookupCache(key),调用成功说明在缓存里拿到了值,用setSinkView()设置之并返回。
如果上一步没有成功,就要采用g.load(ctx, key, dest)来获取需要设置的value了:
|
|
这里先忽略一些细节,可以看出方法会依次尝试g.getFromPeer(ctx, peer, key)和g.getLocally(ctx, key, dest)来获取值。为了找到和演示代码中创建Group实例时传入的groupcache.GetterFunc参数产生的关联性,这里主要查看一下g.getLocally(ctx, key, dest)的代码:
|
|
代码中g.getter就是参数groupcache.GetterFunc,它定义了如何获取本地数据,可以从磁盘加载,也可以从数据库得到。
小结
本篇运行了一个Groupcache例子,熟悉这个分布式KV缓存系统的操作,通过分析相关代码了解了数据的查找流程。