上一个用java实现的版本,这里用go也实现了一遍:
type CacheDemo struct {
CacheMap map[string]*model.Config
ConfigModel model.ConfigModel `inject:""`
syncLock *sync.RWMutex
}
func (c *CacheDemo) ReadConfig() (err error) {
configList, err := c.ConfigModel.SelectAll()
if err != nil {
return
}
cacheMap := make(map[string]*model.Config)
for _, config := range configList {
key := config.Key
cacheMap[key] = config
}
c.syncLock.Lock()
defer c.syncLock.Unlock()
c.CacheMap = cacheMap
return
}
// 这里可以优化一下,
// 首先开启读锁,从缓存中取数据,
// 如果缓存中没取到数据,释放读锁,上写锁,然后查数据库
// 如果数据库中也没取到数据,返回空,否则写进缓存
// 最后释放写锁,再上读锁,最后再释放读锁(至于这里为啥要多此一举,自己想想!)
func (c *CacheDemo) GetConfig(key string) *model.Config {
c.syncLock.RLock()
defer c.syncLock.RUnlock()
return c.CacheMap[key]
}
func (c *CacheDemo) Init() {
c.CacheMap = make(map[string]*model.Config)
c.syncLock = &sync.RWMutex{}
}
func (c *CacheDemo) Start() {
err := c.ReadConfig()
if err != nil {
log.Errorf("load Config have err = %s", err.Error())
}
// 启动一个协程定时拉取数据库所有信息存进缓存
go func() {
tick := time.Tick(5 * time.Minute)
for {
select {
case <-tick:
err := c.ReadConfig()
if err != nil {
log.Errorf("load Config have err = %s", err.Error())
}
}
}
}()
}