本地缓存

针对使用非常频繁的表,如某些配置表,往往查询非常频繁并且是表非常小。这个时候可以采取缓存到内存中,定时的去reload 数据,刷新缓存。

核心结构体

type LoadDataFunc func(ctx context.Context, c *cache.Cache) (map[string]interface{}, error)type LocalCache struct {*cache.Cachename                    string // cache namelastUpdateTime          int64ctx                     context.ContextReloadIncrementInterval time.Duration // wait for reload dataloadFunc                LoadDataFunc // how to load, load whatsync.Mutex//flush bool
}

使用中还是主要依托于

 "github.com/patrickmn/go-cache"

已经帮忙实现个很大一部分功能,没有必要重复造轮子。
关键实现就在于

  • 如何检测时间到达然后调用reload 方法去重新load 数据。这个reload的时间间隔和load数据的时间都是应该客户应该注意的点。
  • reload 方法的时间,返回全量数据,转为cache 的格式。

实现

package local_cacheimport ("context""fmt""github.com/patrickmn/go-cache""sync""time"
)type LoadDataFunc func(ctx context.Context, c *cache.Cache) (map[string]interface{}, error)type LocalCache struct {*cache.Cachename                    string // cache namelastUpdateTime          int64ctx                     context.ContextReloadIncrementInterval time.Duration // wait for reload dataloadFunc                LoadDataFunc // how to load, load whatsync.Mutex//flush bool
}func (lc *LocalCache) GetName() string {return lc.name
}func (lc *LocalCache) String() string {return fmt.Sprintf("name=%s lastUpdateTime:%s ReloadIncrementInterval:%d loadFunc:%s cache_len:%d", lc.name, utils.ConvertTimestampToString(lc.lastUpdateTime),lc.ReloadIncrementInterval, utils.GetFuncName(lc.loadFunc), lc.Cache.ItemCount())
}func (lc *LocalCache) run(ctx context.Context) {ticker := time.NewTicker(lc.ReloadIncrementInterval)for {select {case <-ticker.C:lc.Reload(ctx)}}
}func (lc *LocalCache) Run() {// in case panicdefer func() {if err := recover(); err != nil {go lc.run(lc.ctx)}}()// reload firstif err := lc.Reload(lc.ctx); err != nil {panic(err)}go lc.run(lc.ctx)
}func (lc *LocalCache) Clear() {lc.Cache.Flush()lc.lastUpdateTime = 0
}func (lc *LocalCache) AllKey() []string {//msg := "all key="strList := []string{}for k, _ := range lc.Cache.Items() {strList = append(strList, k)}return strList
}func (lc *LocalCache) Reload(ctx context.Context) error {// add lock for reloadlc.Lock()defer lc.Unlock()dataMap, e := lc.loadFunc(ctx, lc.Cache)if e != nil {return e}cacheItems := transformGoCacheItem(dataMap)lc.Cache = cache.NewFrom(-1, -1, cacheItems)lc.lastUpdateTime = time.Now().Unix()return nil
}func transformGoCacheItem(m map[string]interface{}) map[string]cache.Item {var ans = make(map[string]cache.Item)for k, v := range m {ans[k] = cache.Item{Object:     v,Expiration: -1,}}return ans
}func NewLocalCache(ctx context.Context, name string, incrementInterval time.Duration, fn LoadDataFunc) *LocalCache {c := &LocalCache{name:                    name,ctx:                     ctx,ReloadIncrementInterval: incrementInterval,loadFunc:                fn,//flush:             true,}// need to init or get string method may panic for cache was nilm := make(map[string]cache.Item)c.Cache = cache.NewFrom(cache.NoExpiration, cache.NoExpiration, m)return c
}

关键点主要就在于run 方法,开启协程,死循环去reload 数据到内存。在发生panic 时重新拉起。

使用

使用 New 方法返回实例。设置好loadFunc 以及检测时间间隔即可。再返回实例之后需要调用Run方法才算启动。

遇到的问题

  • 这里注意加载的顺序问题,要等DB 连接后才能去做load 的操作,这是需要注意的地方。
  • 时间间隔和load DB 时间的选择。

优化点

综合之前的检测db 更新机制。可以定时检测表结构的变化还决定reload 的时机。

golang 本地缓存相关推荐

  1. Golang 本地缓存选型对比及原理总结

    提到本地缓存大家都不陌生,只要是个有点经验的后台开发人员,都知道缓存的作用和弊端.本篇文章我们就来简单聊聊在 golang 做业务开发的过程中,本地缓存的一些可选的开源方案.分析它们的特点,以及内部的 ...

  2. 高性能本地缓存Ristretto(一)——存储策略

    Ristretto是Dgraph基于golang实现的一个高性能的本地缓存库.特点是高命中率,高吞吐量,可自定义存储成本,支持一些自定义回调函数,并提供了较多的统计信息. 本文将主要讲述Ristret ...

  3. 微信小程序学习Course 8 本地缓存API

    微信小程序学习Course 8 本地缓存API 本篇随笔主要介绍微信小程序本地缓存API函数,微信小程序可以在本地缓存一些关键词数据,每一条关键词对应一段字符串.微信小程序提供了以下API函数. 8. ...

  4. php缓存数据到本地缓存,本地缓存localStorage的使用方法

    本篇文章的使用方法来自于实际开发,详细介绍AppCan手机框架本地缓存localStorage的使用方法. 在手机应用中,存储本地数据是必不可少的功能,例如我们可以在手机中存储用户自定义设置.传递数据 ...

  5. 万字详解本地缓存之王 Caffeine

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 来自:r6d.cn/UXR4 概要 Caffeine[1] ...

  6. 教你设计一个超牛逼的本地缓存!

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 来源:ksfzhaohui juejin.im/post/5dd9 ...

  7. 如何设计一个牛逼的本地缓存

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 来源:ksfzhaohui juejin.im/post/5dd9 ...

  8. 如何设计一个本地缓存

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 来源:http://i7q.cn/4xPYgB 前言 最近在看My ...

  9. 如何设计一个牛逼的本地缓存!

    来源:ksfzhaohui | http://dwz.win/Ws4 最近在看Mybatis的源码,刚好看到缓存这一块,Mybatis提供了一级缓存和二级缓存:一级缓存相对来说比较简单,功能比较齐全的 ...

最新文章

  1. leetcode002 add_two_numbers
  2. 半折预售:新书-R语言数据可视化之美|ggplot2作者推荐
  3. [Bjoi2014]大融合
  4. javaweb 之javascript 结合
  5. postgresql 目录结构
  6. OpenCV3 Java 机器学习使用方法汇总
  7. 膜拜大丹(结论+二元环)
  8. 使用Epoll 在 Linux 上开发高性能应用服务器
  9. 回文质数(洛谷P1217题题解,Java语言描述)
  10. 又一个好友离开北京了.....
  11. sqlalchemy in查询优化_SQL高级:代码实战 SQL 单表优化
  12. 30 分钟学会 Flex 布局
  13. 【AtCoder】ARC100 题解
  14. python怎么做项目_通过例子说明如何维护好一个Python开源项目
  15. JAVA 基础算法汇总(持续更新)
  16. MySQL书籍和资料
  17. 【历史上的今天】2 月 22 日:Red Hat Enterprise Linux 问世;BASIC 语言作者出生;计算机协会创始人诞生
  18. 常用数据分析的基本方法
  19. 传统文化中,沉香对养身、养心、养神的功效
  20. 方舟手游服务器自动重启,方舟适者生存连接服务器重启怎么办_连接服务器重启解决方法_快吧单机游戏...

热门文章

  1. 用python脚本分类和改名照片和视频
  2. php 实现防盗链,php简单防盗链实现方法
  3. 1.4 java学习的环境准备
  4. 软件测试人员如何去分析及提高用户体验?
  5. 大数据风控,互联网有盾可依
  6. SQL优化(数据库调优)
  7. 使用VBA在工作表中快速插入行
  8. Jetson nano 的三种供电方式
  9. [元带你学: eMMC协议 7] eMMC 概述 与 eMMC总线协议
  10. 【六袆 - MySQL】MySQL5.7官方文档;MySQL5.7英文版;MySQL5.7英文版翻译成中文;