闽公网安备 35020302035485号
Redis和MySQL的双写一致性指的是在同时使用缓存和数据库存储数据的时候,保证Redis和MySQL中数据的一致性。用户发起请求,先从Redis中查取数据,有数据就直接返回,没有数据就从MySQL中查询数据,并且存储到Redis中,然后返回。从MySQL中查询到数据再存入Redis中这个步骤称为回写。
func(dao * UserDAO) FindByID(c context.Context, userID int64)(u domain.User, err error) {
db: =dao.db rdb: =dao.rdb key: =fmt.Sprintf("user:%v", userID)
// 堆代码 duidaima.com
// 1. 从缓存中查询数据,如果有数据就返回
var user domain.User val, err: =rdb.Get(c, key).Result() if val != "" && err == nil {
err: =json.Unmarshal([] byte(val), &user) if err == nil {
return user,
nil
}
}
// 2. 没有查到数据就加锁再查一次
mu.Lock() defer mu.Unlock() val,
err = rdb.Get(c, key).Result()
// 2.1 从缓存中查到数据就直接返回
if val != "" && err == nil {
err: =json.Unmarshal([] byte(val), &user) if err == nil {
return user,
nil
}
}
// 2.2 没有从缓存中查到数据就从数据库中查询
err = db.Where("id=?", userID).First( & user).Error
if err != nil {
return user,
err
}
// 3. 将从数据库中拿到的数据写到缓存中
userStr,
err: =json.Marshal(user) if err == nil {
rdb.Set(c, key, userStr, 1000 * time.Second)
}
return user,
nil
}
数据库和缓存一致性的几种更新策略
上面说的是查询策略,接下来说一下数据库和缓存一致性的更新策略。比如先往MySQL中灌入1万条数据,再同步到Redis中,可以在凌晨升级,给出升级提示。




func (dao *UserDAO) UpdateUserData(c context.Context, userID int64, name string) (user User, err error) {
db := dao.db
rdb := dao.rdb
key := fmt.Sprintf("user:%v", userID)
user.ID = userID
// 先更新数据库中的数据
u := User{
Name: name,
}
err = db.Model(&user).
Select("Name").
Where("id=?", userID).Updates(u).Error
if err != nil {
return user, err
}
// 再删除缓存中的数据
err = rdb.Del(c, key).Err()
if err != nil {
return user, err
}
return user, nil
}
5.比较稳妥的方式