Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1861444
  • 博文数量: 152
  • 博客积分: 3730
  • 博客等级: 上尉
  • 技术积分: 3710
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-02 14:36
个人简介

减肥,运动,学习,进步...

文章分类

全部博文(152)

文章存档

2016年(14)

2015年(17)

2014年(16)

2013年(4)

2012年(66)

2011年(35)

分类: LINUX

2016-06-05 12:28:16

    是   最新的作品,目标在于取代一部分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交互。这部分代码可参考。这部分代码主要分析了缓存部分的实现,代码如下:

点击(此处)折叠或打开

  1. package main

  2. import (
  3.     "flag"
  4.     "fmt"
  5.     "github.com/golang/groupcache"
  6.     "groupcache/api"
  7.     "groupcache/client"
  8.     "net"
  9.     "net/http"
  10.     "net/rpc"
  11.     "os"
  12.     "strconv"
  13. )

  14. type Frontend struct {
  15.     cacheGroup *groupcache.Group //groupcache Group
  16. }

  17. func (s *Frontend) Get(args *api.Load, reply *api.ValueResult) error { //从cache中去取key值,实际是rpc的函数
  18.     var data []byte
  19.     fmt.Printf("cli asked for %s from groupcache\n", args.Key)

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

  21.     reply.Value = string(data)
  22.     return err
  23. }

  24. func NewServer(cacheGroup *groupcache.Group) *Frontend {
  25.     server := new(Frontend)
  26.     server.cacheGroup = cacheGroup //cachegroup
  27.     return server
  28. }

  29. func (s *Frontend) Start(port string) { //tcp的rpc服务
  30.     rpc.Register(s)
  31.     rpc.HandleHTTP()
  32.     l, e := net.Listen("tcp", port)
  33.     if e != nil {
  34.         fmt.Println("fatal")
  35.     }
  36.     http.Serve(l, nil)
  37. }

  38. func main() {
  39.     var port = flag.String("port", "8001", "groupcache port")
  40.     flag.Parse()

  41.     peers := groupcache.NewHTTPPool("" + *port) //注册groupcache的http服务
  42.     client := new(client.Client)
  43.     var stringcache = groupcache.NewGroup("SlowDBCache", 64<<20, groupcache.GetterFunc( //该函数用于获取实际的数据,这部分通常是从源获取数据
  44.         func(ctx groupcache.Context, key string, dest groupcache.Sink) error {
  45.             result := client.Get(key)
  46.             fmt.Printf("asking for %s from dbserver\n", key)
  47.             dest.SetBytes([]byte(result))
  48.             return nil
  49.         })) //创建一个Group

  50.     peers.Set("8001", "8002", "8003") //设置对端信息
  51.     frontendServer := NewServer(stringcache) //rpc的服务器
  52.     i, err := strconv.Atoi(*port)
  53.     if err != nil {
  54.         fmt.Println(err)
  55.         os.Exit(2)
  56.     }

  57.     var frontEndport = ":" + strconv.Itoa(i+1000) //prc的端口为900x
  58.     go frontendServer.Start(frontEndport) //启动rpc的服务,goroutine,这部分用于cli、db之间的交互

  59.     fmt.Println(stringcache)
  60.     fmt.Println("cachegroup slave string on " + *port)
  61.     fmt.Println("fronend start on " + frontEndport)
  62.     http.ListenAndServe("127.0.0.1:"+*port, http.HandlerFunc(peers.ServeHTTP)) //启动http的服务,实际上是启动了GroupCache的服务
  63. }
  从上述的代码可知,使用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的代码进行进一步的分析。
阅读(3198) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~