111 发表于 2018-9-19 13:22:28

golang开发缓存组件

  代码地址github:cache
  花了一天时间看了下实验楼的cache组件,使用golang编写的,收获还是蛮多的,缓存组件的设计其实挺简单的,主要思路或者设计点如下:


[*]全局struct对象:用来做缓存(基于该struct实现增删改查基本操作)
[*]定时gc功能(其实就是定时删除struct对象中过期的缓存对):刚好用上golang的ticker外加channel控制实现
[*]支持缓存写文件及从文件读缓存:其实就是将这里的key-value数据通过gob模块进行一次编解码操作
[*]并发读写:上锁(golang支持读写锁,一般使用时在被操作的struct对象里面声明相应的锁,即sync.RWMutex,操作之前先上锁,之后解锁即可)
  其实大概就是这么多,下面来分解下:

1、cache组件
  要保存数据到缓存(即内存中),先要设计数据结构,cache一般都有过期时间,抽象的struct如下:
  

type Item struct {  
Object   interface{} //数据项
  
Expiration int64       //数据项过期时间(0永不过期)
  
}
  

  
type Cache struct {
  
defaultExpiration time.Duration //如果数据项没有指定过期时使用
  
items             mapItem
  
mu                sync.RWMutex//读写锁
  
gcInterval      time.Duration //gc周期
  
stopGc            chan bool   //停止gc管道标识
  
}
  

  其中,Cache struct为全局缓存对象,缓存的key-value类型为Item,其中包含Object类型、Expiration类型,Object类型设计为interface{}就是为了可以缓存任意数据。

2、过期处理
  下面是判断item中的某项是否过期:
  

func (item Item) IsExpired() bool {  
if item.Expiration == 0 {
  
return false
  
}
  
return time.Now().UnixNano() > item.Expiration //如果当前时间超则过期
  
}
  

3、定时gc
  想要实现定时功能,要用到golang的time包,使用NewTicker声明一个ticker类型,再使用for循环读取ticker.C数据,循环一次则取一次数据,进行一次DeleteExpired操作,Cache中的stopGc用于结束ticker,这样整个gcLoop()便会停止,使用select监听通道数据分别处理如下:
  

//循环gc  
func (c *Cache) gcLoop() {
  
ticker := time.NewTicker(c.gcInterval) //初始化一个定时器
  
for {
  
select {
  
case
页: [1]
查看完整版本: golang开发缓存组件