侧面剖析cache2go

x_zhaohu · · 1785 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

学习开源缓存库,cache2g0是作为Go新手来说,比较容易上手的library。

Cache2go

Concurrency-safe golang caching library with expiration capabilities.
cache2g0是一个key-value格式的保证并发安全并带有过期控制的缓存库。

你如何来设计一个缓存库呢?

最方便的方式: key-value形式。类似redis那样,我先画一张表,然后在表中存放n个key-value。


cache_design.png

Cache2go的实现就是这个实现原理,在上图基础上添加了安全性和过期控制等功能。

部分Cache2go源码解读

先让我们来看看Cache2go中有关的结构体:CacheTable,CacheItem

//CacheTable
type CacheTable struct {
    sync.RWMutex                                 // 互斥锁
    name              string                     // 表名
    items             map[interface{}]*CacheItem // item的集合
    cleanupTimer      *time.Timer                // 设置清理时间(处于等待状态)
    cleanupInterval   time.Duration              // 设置清理时间段
    logger            *log.Logger                // 设置日志
    loadData          func(key interface{}, args ...interface{}) *CacheItem
    addedItem         func(item *CacheItem)
    aboutToDeleteItem func(item *CacheItem)
}

//CacheItem
type CacheItem struct {
    sync.RWMutex                        // 互斥锁
    key           interface{}           // data-key
    data          interface{}           // data-value
    lifeSpan      time.Duration         // 生命周期
    createdOn     time.Time             // 创建时间
    accessedOn    time.Time             // 最后访问时间
    accessCount   int64                 // 访问次数
    aboutToExpire func(key interface{}) // TODO
}

为了保证其并发安全性,都带有sync.RWMutex,维持操作的原子性。并带有时间戳来实现过期控制。至于那些回调函数,我也是第一次看见这种写法。
Cache2go的作者们,根据这两个struct分别开放了许多getter&setter方法,使用者只需调用即可,代码实现过程中也有对用户是否设置过属性进行判断,来确保程序的健壮性。

举个例子:

CacheTable中包含logger字段,并且编写了SetLogger(logger)来让用户实现logger打印,并实现了log(v...)方法,让用户可选实现SetLogger(logger),如果用户不想打印日志,那么不需要调用SetLogger(logger)

func (table *CacheTable) log(v ...interface{}) {
    if table.logger == nil {
        return
    }
    table.logger.Println(v)
}
创建表并添加Item

通过创建一个缓存表并添加缓存Item来剖析源码,实现代码如下:

// new Cache
    cache := cache2go.Cache("myCache")

    // set logger
    logger := log.New(os.Stdout, "DEBUG", log.Ltime)
    cache.SetLogger(logger)

    // will storage data
    val := myStruct{"This is a test!", []byte{}}

    // Add Item : key, duration, stor_data
    cache.Add("someKey", 5*time.Second, &val)
创建一个表

Cache2go中调用Cache(tableName)方法来实现创建,内部使用map来实现的,先通过tableName关键字在map中查找,如果存在则直接返回,否则先出创建,之后返回。


Cache
向表中添加CacheItem
  • 通过调用NewCacheItem(key, lifeSpan, value)来完成CacheItem的初始化
  • 接下里需要添加将CacheItem添加到CacheTable中
  • CacheTable的对象通过调用自身的addInternal(cacheItem)完成添加,并检查是否有过期的缓存
  • addInternal(cacheItem)中调用自身的expiraionCheck()来完成检查.

add.png

这里只是代码简单描述了下,主要掌握其设计思想就好啦。详情还请移步cache2g0

需要扩充的知识点(后续更新...)

  • struct中的回调函数
  • sync.RWMutex源码的解读
  • time源码的解读

精彩文章,持续更新,请关注微信公众号:


帅哥美女扫一扫

有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:x_zhaohu

查看原文:侧面剖析cache2go

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1785 次点击  
加入收藏 微博
1 回复  |  直到 2017-07-10 03:56:18
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传