使用Redis实现朋友圈点赞功能的步骤说明
1. 数据结构设计
每条朋友圈的点赞用户集合
键名格式:post:{post_id}:likes
,类型为Set
,存储所有点赞用户的ID。
示例:post:123:likes
→ 存储用户IDuser1
,user2
,user3
。
每个用户点赞的朋友圈集合
键名格式:user:{user_id}:liked_posts
,类型为Set
,存储用户点过赞的朋友圈ID。
示例:user:456:liked_posts
→ 存储朋友圈IDpost:123
,post:456
。
2. 核心操作实现
2.1 用户点赞
bash
# 原子化操作:使用Lua脚本确保两个集合同时更新
EVAL "redis.call('SADD', KEYS[1], ARGV[1]); redis.call('SADD', KEYS[2], KEYS[3]); return 1;" 3 post:123:likes user:456:liked_posts post:123 456
步骤解释:
- 将用户ID添加到朋友圈的点赞用户集合(
SADD post:123:likes 456
)。 - 将朋友圈ID添加到用户的点赞记录集合(
SADD user:456:liked_posts post:123
)。 - 使用Lua脚本保证原子性,避免部分操作失败导致数据不一致。
2.2 用户取消点赞
bash
# 原子化操作:使用Lua脚本移除两个集合中的数据
EVAL "redis.call('SREM', KEYS[1], ARGV[1]); redis.call('SREM', KEYS[2], KEYS[3]); return 1;" 3 post:123:likes user:456:liked_posts post:123 456
步骤解释:
- 从朋友圈的点赞用户集合中移除用户ID(
SREM post:123:likes 456
)。 - 从用户的点赞记录集合中移除朋友圈ID(
SREM user:456:liked_posts post:123
)。
2.3 获取点赞用户列表
bash
SMEMBERS post:123:likes # 返回集合中所有用户ID
示例输出:1) "user1" 2) "user2" 3) "user3"
2.4 统计点赞数量
bash
SCARD post:123:likes # 返回集合元素数量
示例输出:(integer) 3
2.5 检查用户是否已点赞
bash
SISMEMBER post:123:likes 456 # 返回1(已点赞)或0(未点赞)
示例输出:(integer) 1
3. 性能优化与扩展
分片存储:
若朋友圈数量极大,按post_id
哈希分片(如post_shard:{hash}:{post_id}:likes
)分散键存储。缓存热点数据:
高频访问的朋友圈点赞列表(如热门帖子)可缓存到本地或Redis的String
类型(需序列化)。异步持久化:
通过消息队列(如Kafka)将点赞操作异步写入数据库,降低Redis压力。
4. 数据结构对比
操作 | 命令 | 时间复杂度 | 适用场景 |
---|---|---|---|
添加/取消点赞 | SADD /SREM | O(1) | 快速单次操作 |
获取点赞列表 | SMEMBERS | O(N) | 小规模数据(建议分页) |
统计点赞数 | SCARD | O(1) | 实时统计 |
检查用户是否点赞 | SISMEMBER | O(1) | 动态判断 |
5. 完整流程图
用户点击点赞 → 调用API → Redis Lua脚本(SADD两集合) → 返回成功
用户取消点赞 → 调用API → Redis Lua脚本(SREM两集合) → 返回成功
前端展示 → 查询SCARD(计数)和SMEMBERS(列表) → 渲染界面
6. 异常处理
网络重试:
客户端在超时后重试点赞操作,服务端通过SISMEMBER
检查避免重复处理。数据一致性校验:
定时任务扫描post:*:likes
与user:*:liked_posts
,修复不一致数据。
总结
通过Redis的Set
数据结构,结合Lua脚本保证原子性操作,能够高效实现朋友圈的点赞、取消、计数及列表展示功能。针对高并发场景,可通过分片和缓存优化性能,同时通过异步持久化和定时任务确保数据最终一致性。