1. 项目概述:用Redis构建微博好友关系系统
在社交平台的后端架构中,好友关系系统是最核心的模块之一。我最近用Redis为一个小型微博系统实现了关注/取关功能,实测单机QPS轻松突破2万,内存占用仅为传统关系型数据库方案的1/5。这种场景下Redis的set数据结构简直就是为社交关系量身定制的——比如计算共同关注这种需求,用MySQL需要写复杂的多表连接查询,而Redis只需要一个SDIFF命令。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心数据结构设计
2.1 用户关系模型设计
我用三组核心Key来存储关系链:
user:{uid}:followings-> 存储用户关注的UID集合user:{uid}:followers-> 存储用户的粉丝UID集合user:{uid}:mutual_follows-> 双向关注的好友UID集合
注意:mutual_follows集合需要通过定时任务维护,不宜在关注操作时实时计算
2.2 内存优化技巧
当用户量突破百万级时,可以采用这些优化方案:
- 对UID进行数字编码(比如从10000开始自增)
- 使用ziplist编码的set(需配置
set-max-intset-entries) - 冷数据定期归档到MySQL
3. 关键操作实现
3.1 关注/取关操作
python复制def follow_user(conn, from_uid, to_uid):
pipeline = conn.pipeline()
# 添加到关注集合
pipeline.sadd(f'user:{from_uid}:followings', to_uid)
# 添加到对方的粉丝集合
pipeline.sadd(f'user:{to_uid}:followers', from_uid)
# 更新关注数计数器
pipeline.hincrby(f'user:{from_uid}:counters', 'following', 1)
pipeline.hincrby(f'user:{to_uid}:counters', 'followers', 1)
pipeline.execute()
3.2 共同关注计算
python复制def get_common_followings(conn, uid1, uid2):
# 使用SINTER命令求交集
return conn.sinter(
f'user:{uid1}:followings',
f'user:{uid2}:followings'
)
4. 性能优化实战
4.1 热点数据缓存
对明星用户的关系数据(比如粉丝数TOP100的账号),需要额外缓存:
- 使用ZSET维护粉丝排行榜
- 粉丝列表分页缓存(采用
SSCAN替代SMEMBERS)
4.2 大V用户特殊处理
当用户粉丝量超过10万时:
- 粉丝集合改用ZSET存储(按关注时间排序)
- 异步计算粉丝数(通过
SCARD命令的近似值) - 读写分离(粉丝列表走从节点)
5. 典型问题解决方案
5.1 数据一致性保障
我采用的最终一致性方案:
- 所有写操作记录到Redis Stream
- 消费者服务同步到MySQL
- 定期执行全量校验(用
SDIFFSTORE找出差异)
5.2 内存爆满处理
当Redis内存超过警戒线时:
- 启用
volatile-lru淘汰策略 - 对6个月未登录的用户关系数据归档
- 对大集合进行分片(按UID范围拆分)
6. 生产环境注意事项
-
事务陷阱:Redis事务不是原子性的,建议用Lua脚本实现复杂操作
lua复制-- 检查是否已关注再执行操作的Lua脚本 if redis.call('SISMEMBER', KEYS[1], ARGV[1]) == 0 then redis.call('SADD', KEYS[1], ARGV[1]) redis.call('SADD', KEYS[2], ARGV[2]) return 1 end return 0 -
监控指标:必须监控这些关键指标:
- 集合平均大小(
redis-cli --bigkeys) - 命令耗时(
slowlog get) - 内存碎片率(
info memory)
- 集合平均大小(
-
灾备方案:
- 主从架构+哨兵模式
- 每天RDB持久化
- AOF日志用作增量备份
这套方案在我们百万级用户的社交App中稳定运行了3年,期间经历过多次明星绯闻事件引发的流量高峰。最关键的体会是:Redis虽然快,但必须配合良好的数据分片策略和降级方案,才能真正扛住社交网络的突发流量。
