在一个我们需要更新缓存数据的场景下时,有许多选择的余地,django中很多时候使用celery定时任务,但是单用celery定时任务也许无法保证数据的实时更新。
比如django框架中包含了很多signal,单独使用signal的话并没有什么性能上的优势,通过结合一些类似celery异步任务使用真的很好用,基本可以做到数据的实时更新。
在golang的gorm框架中也提供了callback方法,具体可以参考官方文档https://gorm.io/docs/hooks.html,配合go天然的并发优势简直爽到不行0.0
下面以更新redis缓存为例
package main
import (
"fmt"
"github.com/go-redis/redis"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
"github.com/vmihailenco/msgpack"
"log"
"strconv"
"sync"
)
type user struct {
Id uint `json:"id" gorm:"primary_key"`
Name string `json:"name" gorm:"not null"`
}
var wg sync.WaitGroup
func redisCon() *redis.Client{
conn := redis.NewClient(&redis.Options{
Addr: "192.168.50.15:6379",
Password: "",
DB: 1,
})
err := conn.Ping().Err()
if err != nil {
log.Fatal("连接redis失败")
}
return conn
}
// 刷新
func flashInfo(u *user) {
defer wg.Done()
conn := redisCon()
defer conn.Close()
// 序列化
info, _ := msgpack.Marshal(u)
// 存入hash
idStr := strconv.Itoa(int(u.Id))
err := conn.HSet("user_info", idStr, info).Err()
if err != nil {
fmt.Printf("更新缓存出错了,err:%s",err.Error())
return
}
fmt.Println("更新缓存完成了")
}
// 获取信息
func getInfo(key,field string){
conn := redisCon()
defer conn.Close()
val, _ := conn.HGet(key, field).Bytes()
var u user
err := msgpack.Unmarshal(val,&u)
if err != nil {
fmt.Printf("获取缓存数据出错了,err:%s\n",err.Error())
return
}
fmt.Printf("用户名已被更新为:%s\n",u.Name)
}
func beforeUpdate(scope *gorm.Scope) {
fmt.Println("我要准备更新user了")
}
func afterUpdate(scope *gorm.Scope) {
fmt.Println("更新user成功了,我要准备更新缓存了")
value := scope.IndirectValue().Interface()
// 转换对应结构体
u := value.(user)
fmt.Println("我开始更新缓存了")
// 更新缓存
wg.Add(1)
go flashInfo(&u)
wg.Wait()
idStr := strconv.Itoa(int(u.Id))
getInfo("user_info",idStr)
}
func (u *user) updateUser(db *gorm.DB) error {
db.Model(u).Update("name",u.Name).Callback().Update().After("gorm:beforeUpdate").Before("gorm:beforeUpdate")
return nil
}
func main() {
db, err := gorm.Open("mysql", "edu:123456@tcp(192.168.50.15:33306)/gormtest?charset=utf8&parseTime=True")
if err != nil {
fmt.Println(err)
}
defer db.Close()
u := &user{
Id: 1,
Name: "fff",
}
// 注册方法
db.Callback().Update().Register("gorm:beforeUpdate", beforeUpdate)
db.Callback().Update().Register("gorm:afterUpdate", afterUpdate)
u.updateUser(db)
}