学习开源缓存库,cache2g0是作为Go新手来说,比较容易上手的library。
Cache2go
Concurrency-safe golang caching library with expiration capabilities.
cache2g0是一个key-value格式的保证并发安全并带有过期控制的缓存库。
你如何来设计一个缓存库呢?
最方便的方式: key-value形式。类似redis那样,我先画一张表,然后在表中存放n个key-value。
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中查找,如果存在则直接返回,否则先出创建,之后返回。
向表中添加CacheItem
- 通过调用
NewCacheItem(key, lifeSpan, value)
来完成CacheItem的初始化 - 接下里需要添加将CacheItem添加到CacheTable中
- CacheTable的对象通过调用自身的
addInternal(cacheItem)
完成添加,并检查是否有过期的缓存 - 在
addInternal(cacheItem)
中调用自身的expiraionCheck()
来完成检查.
这里只是代码简单描述了下,主要掌握其设计思想就好啦。详情还请移步cache2g0
需要扩充的知识点(后续更新...)
- struct中的回调函数
- sync.RWMutex源码的解读
- time源码的解读
精彩文章,持续更新,请关注微信公众号:
有疑问加站长微信联系(非本文作者)