这是我参与「第三届青训营 -后端场」笔记创作活动的第4篇笔记
前言
在之前的版本中,我们使用了 Mysql 来实现关注和被关注的数据存储。
但是,考虑到关注和被关注是一个高频操作,使用 MySQL 直接记录的话,在高并发场景下会有很明显的卡顿,甚至会出现 MySQL 服务器宕机
所以我打算用 redis 重构这个模块。
基本思路
每个用户有都有一个关注 set 和粉丝 set,set 的存储的是用户的唯一 ID。
每当用户关注某人时,就会被写入到关注 set 中,同时对方的粉丝 set 也会记录当前用户
当需要判断两人是否进行互相关注时,可以直接使用 redis 中的 集合操作,找出对方关注 set 的交集。
原本我们使用 SQL 来实现这个功能的,性能上并不是很高效。
这样就可以免去使用 MySQL 查询实现了,更高效地提高性能。
注意点
使用 redis 作为缓存需要额外注意“缓存失效”的情况。当 redis 查不到数据时,需要转而查询 MySQL 后端数据库,并且查到数据后,一定要将其更新到 redis 服务器中!
这里有一个提升效率的小细节:在往 redis 服务器更新数据的时候,可以作异步处理,另开一个协程进行更新。
这样当从 MySQL 查询出数据后,不必等待 redis 服务器的更新就可以及时将数据响应了!
代码部分展示
// GetFollowListByRedis use redis to refactor 获取用户的关注列表中的用户信息
func (f FollowDao) GetFollowListByRedis(userId int64) (vo.FollowResponseVo, error) {
// 省略代码
······························
// 1. 从redis中获取关注者的id
res := rdb.SMembers(ctx, userKey)
if res.Err() != nil {
return followList, res.Err()
}
// 缓存失效
if len(res.Val()) == 0 {
list, err := f.GetFollowList(userId)
if err != nil {
return followList, err
}
// 异步执行
go func() {
err := updateUserListToRedis(list.UserList, userKey)
if err != nil {
global.GVA_LOG.Error(exceptions.UpdateRedisFailureError.Error())
global.GVA_LOG.Error(err.Error())
}
}()
return list, nil
}
// 缓存击中
followerIds := utils.String2Int64(res.Val())
// 2. 获取关注者
······························
return followList, nil
}