golang使用groupcache(github.com上golang团队发布)

前端之家收集整理的这篇文章主要介绍了golang使用groupcache(github.com上golang团队发布)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

groupcache 简介

在软件系统中使用缓存,可以降低系统响应时间,提高用户体验,降低某些系统模块的压力.
groupcache是一款开源的缓存组件.与memcache与redis不同的时,groupcache不需要单独的部署,可以作为你程序的一个库来使用. 这样方便我们开发的程序部署.

groupcache使用流程介绍

  • NewGroup创建一个group实例,@H_502_10@
  1. // 创建一个Group实例,
  2. // 第一个参数是group名字.
  3. // 第二个参数是缓冲区大小.
  4. // 第三个参数是回调函数.
  5. func NewGroup(name string,cacheBytes int64,getter Getter) *Group {
  6. return newGroup(name,cacheBytes,getter,nil)
  7. }
  8.  
  9. // If peers is nil,the peerPicker is called via a sync.Once to initialize it.
  10. func newGroup(name string,getter Getter,peers PeerPicker) *Group {
  11. if getter == nil {
  12. panic("nil Getter")
  13. }
  14. mu.Lock()
  15. defer mu.Unlock()
  16. initPeerServerOnce.Do(callInitPeerServer)
  17. if _,dup := groups[name]; dup {
  18. panic("duplicate registration of group " + name)
  19. }
  20. g := &Group{
  21. name: name,getter: getter,peers: peers,cacheBytes: cacheBytes,loadGroup: &singleflight.Group{},}
  22. if fn := newGroupHook; fn != nil {
  23. fn(g)
  24. }
  25. groups[name] = g
  26. return g
  27. }
  • 在创建Group实例的过程中,传入了一个回调函数,通过这个回到函数,将需要缓存的数据写入到cache中.@H_502_10@
  • 后边就可以通过Group提供的Get方法,按照key值,获取缓存数据.
    下面来看看Group的Get方法.@H_502_10@
  1. func (g *Group) Get(ctx Context,key string,dest Sink) error {
  2. // 如果注册了peer,则下边的函数生效,否则无效.
  3. g.peersOnce.Do(g.initPeers)
  4.  
  5. // Stats的Gets 自增1
  6. // 统计分析使用
  7. g.Stats.Gets.Add(1)
  8.  
  9. // dest不能为空,否则报错.
  10. if dest == nil {
  11. return errors.New("groupcache: nil dest Sink")
  12. }
  13.  
  14. // 根据key值在cache中查找缓存的值.
  15. value,cacheHit := g.lookupCache(key)
  16.  
  17. if cacheHit {
  18. g.Stats.CacheHits.Add(1)
  19. return setSinkView(dest,value)
  20. }
  21.  
  22. // Optimization to avoid double unmarshalling or copying: keep
  23. // track of whether the dest was already populated. One caller
  24. // (if local) will set this; the losers will not. The common
  25. // case will likely be one caller.
  26. destPopulated := false
  27. value,destPopulated,err := g.load(ctx,key,dest)
  28. if err != nil {
  29. return err
  30. }
  31. if destPopulated {
  32. return nil
  33. }
  34. return setSinkView(dest,value)
  35. }
  • 上边的Get方法第一次调用时,其中的g.lookupCache(key)会返回false,主要原因是,缓冲区还没有写入任何有效值.@H_502_10@
  • Get的时候,会执行里面的g.load(ctx,dest)函数. 而load会调用NewGroup传入的第三个参数,即回调函数.@H_502_10@
  1. func (g *Group) getLocally(ctx Context,dest Sink) (ByteView,error) {
  2. err := g.getter.Get(ctx,dest)
  3. if err != nil {
  4. return ByteView{},err
  5. }
  6. return dest.view()
  7. }
  • 上边的g.getter.Get(ctx,dest)即是NewGroup传入的回调函数.@H_502_10@
  • 所以,可以将需要缓存的信息在创建Group实例的时候在回调函数中进行初始化.@H_502_10@
  • 在回到函数中,通过实现了Sink的实例向Group的缓冲区中写入数据.Sink接口信息如下:@H_502_10@
  1. type Sink interface {
  2. // SetString sets the value to s.
  3. SetString(s string) error
  4.  
  5. // SetBytes sets the value to the contents of v.
  6. // The caller retains ownership of v.
  7. SetBytes(v []byte) error
  8.  
  9. // SetProto sets the value to the encoded version of m.
  10. // The caller retains ownership of m.
  11. SetProto(m proto.Message) error
  12.  
  13. // view returns a frozen view of the bytes for caching.
  14. view() (ByteView,error)
  15. }

实现了Sink接口的类如下:

  • stringSink@H_502_10@
  • byteViewSink@H_502_10@
  • protoSink@H_502_10@
  • allocBytesSink@H_502_10@
  • truncBytesSink
    上边几个类都是私有的类,不允许客户端直接创建实例,下边几个类的实例分别可以通过如下几个函数来创建:@H_502_10@
  • StringSink(sp *string) Sink@H_502_10@
  • ByteViewSink(dst *ByteView) Sink@H_502_10@
  • ProtoSink(m proto.Message) Sink@H_502_10@
  • AllocatingByteSliceSink(dst *[]byte) Sink@H_502_10@
  • TruncatingByteSliceSink(dst *[]byte) Sink
    下面来回顾一下上边的回调函数写入缓存信息的流程
    1. 创建实现Sink接口的类实例@H_502_10@
    2. 在回调函数中使用第一步中创建出来的实例提供的方法将数据写入cache中@H_502_10@
    3. 等到客户端使用Group实例来Get缓存时,如果是第一次调用,则执行回调函数,然后返回回调函数中写入的缓存信息,如果不是第一次调用,则直接读取缓存返回.@H_502_10@
    @H_502_10@

总结


  1. groupcache可以当做一个类库来使用.这样很方便我们在项目中灵活的使用. @H_502_10@
  2. groupcache的缓存采用LRU的方式实现,这样大大提高高频缓存的查询效率.@H_502_10@
  3. 可以将回调函数中传入channel变量,这样可以实现缓存数据的更新.原因是回调函数只能执行一次,所以,通过channel可以实现线程之间的方便通信.@H_502_10@
  4. groupcache获取方式
    @H_502_10@
go get github.com/golang/groupcache

温馨提示

以上内容,纯属个人愚见,有高人看出漏洞,请指点,以免瑕疵文章,误人子弟,感激不尽.

e-mail: hzwy23@163.com

猜你在找的Go相关文章