Golang学习--GroupCache的使用

groupcache Brad Fitzpatrick 最新的作品,目标在于取代一部分memcached的功能。以官方的说明是:groupcache is a caching and cache-filling library, intended as a replacement for memcached in many cases. 另外一篇介绍文是「Playing With Groupcache」。跟memcached 差异最大的地方在于「没有更改与删除的功能」,一旦写进去后就不会变动。在放弃update/delete 的特性后,换来的是: >> Cluster 的能力。 >> 处理热点的能力。 以往在memcached server 之间是没有交集的,在groupcache 则是cluster 起来。另外以前在memcached 会因为同时存取同一个key 而造成single CPU overloading 的问题,在groupcache 则透过auto-mirror 机制解决。参考:http://blog.csdn.net/songbohr/article/details/16349989。其中groupcache与memcached最大的区别是不需要启动额外的服务。groupcache作为lib库缓存数据,不需要单独开启服务器,减少了服务器额外维护的代价。

groupcache也常被推荐为适合Golang初学者分析的代码段,这几天我也抽空分析了一下具体的实现,并结合Play With Groupcach简单的测试了GroupCache,实现的基本结构如下所示:

该软件结构图实现了一种只读型静态网站的分布式实现。主要包括三个服务器,其中DB Server是数据库,主要对外提供数据,在实际的场景中可以是NoSql数据库也可能是关系数据库。可对该数据库进行插入、新增数据。缓存服务器,分为前端和GroupCache Server,实际上将Cache Server包含在了业务代码中,其中前端是提供操作的相关接口,而后端部分通常作为业务服务器的一部分,缓存数据可直接被服务器使用。Cli部分主要是用于操作数据量和groupcache server交互。这部分代码可参考https://github.com/capotej/groupcache-db-experiment。这部分代码主要分析了缓存部分的实现,代码如下:

点击(此处)折叠或打开

package main



import (

 "flag"

 "fmt"

 "github.com/golang/groupcache"

 "groupcache/api"

 "groupcache/client"

 "net"

 "net/http"

 "net/rpc"

 "os"

 "strconv"

)



type Frontend struct {

    cacheGroup *groupcache.Group //groupcache Group

}



func (s *Frontend) Get(args *api.Load, reply *api.ValueResult) error { //从cache中去取key值,实际是rpc的函数

    var data []byte

    fmt.Printf("cli asked for %s from groupcache\n", args.Key)



 err := s.cacheGroup.Get(nil, args.Key, groupcache.AllocatingByteSliceSink(&data)) //groupcache中获取数据



    reply.Value = string(data)

    return err

}



func NewServer(cacheGroup *groupcache.Group) *Frontend {

    server := new(Frontend)

    server.cacheGroup = cacheGroup //cachegroup

    return server

}



func (s *Frontend) Start(port string) { //tcp的rpc服务

    rpc.Register(s)

    rpc.HandleHTTP()

    l, e := net.Listen("tcp", port)

 if e != nil {

        fmt.Println("fatal")

 }

    http.Serve(l, nil)

}



func main() {

    var port = flag.String("port", "8001", "groupcache port")

    flag.Parse()



 peers := groupcache.NewHTTPPool("http://localhost:" + *port) //注册groupcache的http服务

    client := new(client.Client)

    var stringcache = groupcache.NewGroup("SlowDBCache", 64<<20, groupcache.GetterFunc( //该函数用于获取实际的数据,这部分通常是从源获取数据

        func(ctx groupcache.Context, key string, dest groupcache.Sink) error {

            result := client.Get(key)

            fmt.Printf("asking for %s from dbserver\n", key)

            dest.SetBytes([]byte(result))

            return nil

 })) //创建一个Group



 peers.Set("http://localhost:8001", "http://localhost:8002", "http://localhost:8003") //设置对端信息

    frontendServer := NewServer(stringcache) //rpc的服务器

    i, err := strconv.Atoi(*port)

 if err != nil {

        fmt.Println(err)

        os.Exit(2)

 }



    var frontEndport = ":" + strconv.Itoa(i+1000) //prc的端口为900x

    go frontendServer.Start(frontEndport) //启动rpc的服务,goroutine,这部分用于cli、db之间的交互



    fmt.Println(stringcache)

    fmt.Println("cachegroup slave string on " + *port)

    fmt.Println("fronend start on " + frontEndport)

  http.ListenAndServe("127.0.0.1:"+*port, http.HandlerFunc(peers.ServeHTTP)) //启动http的服务,实际上是启动了GroupCache的服务

}

从上述的代码可知,使用GroupCache的基本过程如下所示: >> 首先创建一个GroupCache的HTTPool, peers。 >> 创建Group对象, 设置该Group Cache的大小,数据实际获取的方法,其中的 groupcache.GetterFunc对应着实际从源头加载数据的方法,比如从数据库中获取、从文件中获取等。这也是必须的。groupcache.GetterFunc实际上是groupcache.Getter的接口实例。 >> 设置对端GroupCache的地址信息。peers.Set(url1, url2, ...) >> 启动GroupCache的Http服务。在http.ListenAndServe("xxxx", http.HandlerFunc(peers.ServeHTTP)) >> 要获取数据只需要通过创建的Group对象来获取即可。group.Get(xxx)。 后续将对groupcache的代码进行进一步的分析。

原文发布于微信公众号 - Golang语言社区(Golangweb)

原文发表时间:2016-11-16

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏JAVA技术zhai

天下无难试之多线程面试刁难大全

多线程技术在互联网技术方面使用如此广泛,几乎所有的后端技术面试官都要在并发编程的使用和原理方面对小伙伴们进行各种刁难。作为一名在互联网技术行业打击过成百上千名【...

31190
来自专栏Golang语言社区

【Go 语言社区】用Go实现的简易TCP通信框架--转

接触到GO之后,GO的网络支持非常令人喜欢。GO实现了在语法层面上可以保持同步语义,但是却又没有牺牲太多性能,底层一样使用了IO路径复用,比如在LINUX下用了...

422100
来自专栏FreeBuf

我是如何利用CSRF Get DedeCms Shell的

说实话,有一两个月没有审计大厂了,然后随便看到群里有人问dede最新有没有漏洞,就下了一套最新的dede,结果我一看还真发现了。 ? 我们发现后台添加广...

25080
来自专栏有趣的django

Django REST framework+Vue 打造生鲜超市(十二) 十三、首页、商品数量、缓存和限速功能开发

十三、首页、商品数量、缓存和限速功能开发  13.1.轮播图接口实现 首先把pycharm环境改成本地的,vue中local_host也改成本地  (1)goo...

73470
来自专栏数据小魔方

word多文档合并技巧

今天要跟大家安利一些word多文档合并的技巧! 经常要处理word文档的小伙伴儿们,是不是也遇到过这样的难题。 偶尔要把一大堆的word文本文档,弄到一个文档...

36260
来自专栏张善友的专栏

[腾讯社区开放平台]介绍开放授权协议-OAuth

OAuth (开放授权) 是一个开放标准,允许用户授权第三方网站访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方网站或分享他们数据的所...

28170
来自专栏Web项目聚集地

Javascript中的异步

8320
来自专栏学习有记

AlwaysOn 进阶 Level 1:What is "SQL Server AlwaysOn"?

15730
来自专栏大数据文摘

手把手 | 20行Python代码教你批量将PDF转为Word

34950
来自专栏王磊的博客

Node出错导致运行崩溃的解决方案

许多人都有这样一种映像,NodeJS比较快; 但是因为其是单线程,所以它不稳定,有点不安全,不适合处理复杂业务; 它比较适合对并发要求比较高,而且简单的业务场景...

810140

扫码关注云+社区

领取腾讯云代金券