Redis查询缓存与延时双删的实际应用(Golang)
有个小项目,需要弄个树型单词分类,虽然客户那边访问量不大,崩是不可能崩的。但是数据量大了以后,每次打开这个页面都要等个一两秒,属实有点难受。就想着用缓存来装这颗树。
Json数据的结构
"title": "大学",
"key": 1,
"children": [
{
"title": "四级阅读",
"key": 2,
"children": [
{
"title": "8901A",
"key": 3,
"children": null
Golang结构体
// CategoryTree 分类树
type CategoryTree struct {
Title string `json:"title"`
Key int64 `json:"key"`
Children []CategoryTree `json:"children"`
}
查询时使用缓存,加快访问速度
// GetCategorys 获取整个单词分类树
func GetCategorys() ([]models.CategoryTree, bool) {
//分类树
var tree []models.CategoryTree
//检查缓存中是否有数据,如果有,则直接返回
_, jsonStr := redis.GetValueByKey("CategoryTree")
if len(jsonStr) > 0 {
//把Redis中的值解析成golang的结构体
err := json.Unmarshal([]byte(jsonStr), &tree)
//如果解析成功
if err == nil {
//直接返回数据
return tree, true
}
}
//如果缓存中没有数据
/*
多条又臭又长的MySQL查询语句
。。。ba la ba la。。。
查出数据,放进tree里
*/
//将查询到的数据转换为json字符串缓存进redis
jsonTree, _ := json.Marshal(tree)
redis.SetValueByKey("CategoryTree", string(jsonTree), 60*60*720)
}
更新数据时,使用延时双删,清除旧的缓存
// SetCategory 新增单词类别
func SetCategory(categoryName string, fatherId int64, lv int) (string, bool) {
//先删除缓存
redis.SetValueByKey("CategoryTree", "", 1)
//在该函数return前,再开一个协程,负责二次延时删除
defer func() {
go func() {
//延时3秒执行
time.Sleep(time.Second * 3)
//再次删除缓存
redis.SetValueByKey("CategoryTree", "", 1)
}()
}()
/*
MySQL插入语句。。。ba la ba la。。。
*/
if err != nil {
utils.Loger.Println(err)
return "插入失败", false
}
return "插入成功", true
}
Redis数据插入函数
func SetValueByKey(key string, value string, time int) bool {
_, err := conn.Do("SET", key, value, "EX", time)
if err != nil {
utils.Loger.Println(err)
return false
}
return true
}