标签
架构设计
架构设计/系统设计
中间件/Redis
字数
787 字
阅读时间
4 分钟
评论形态分类
状评论(Reddit / 知乎早期)
- 评论天然呈树结构
- 支持多级嵌套
- 强上下文关系
- 缺点:
- 深层递归查询
- 分页困难
- 高并发下性能差
扁平评论(抖音 / B站 / 微博)
- 数据存储扁平
- 展示逻辑由前端控制
- 多级回复“看起来像树”,但底层不是树
- 优点:
- 查询简单
- 易分页
- 高并发友好
本评论系统设计目标:
- 数据库层完全扁平化
- 避免基于
parent_id的递归查询 - 通过
root_id聚合评论主题 - 通过
reply_id / reply_user_id表达回复语义 - 支持:
- 树状展示(Reddit 风格)
- 扁平展示(抖音 / B站 风格)
- 支持评论热度排行(Redis)

评论表设计:
sql
CREATE TABLE comment (
id BIGINT PRIMARY KEY COMMENT '评论ID',
root_id BIGINT NOT NULL COMMENT '根评论ID',
reply_id BIGINT DEFAULT NULL COMMENT '回复的评论ID',
reply_user_id BIGINT DEFAULT NULL COMMENT '被回复用户ID',
reply_user_nick VARCHAR(64) DEFAULT NULL COMMENT '被回复用户昵称快照',
user_id BIGINT NOT NULL COMMENT '评论者用户ID',
user_nick VARCHAR(64) NOT NULL COMMENT '评论者昵称快照',
user_avatar VARCHAR(255) NOT NULL COMMENT '评论者头像快照',
content TEXT NOT NULL COMMENT '评论内容',
status TINYINT NOT NULL DEFAULT 0 COMMENT '状态:0正常 1删除 2屏蔽',
like_count INT NOT NULL DEFAULT 0 COMMENT '点赞数',
reply_count INT NOT NULL DEFAULT 0 COMMENT '回复数',
created_at DATETIME NOT NULL,
updated_at DATETIME NOT NULL,
INDEX idx_root (root_id),
INDEX idx_user (user_id),
INDEX idx_created (created_at)
) COMMENT='评论表';在表中,我们存储用户冗余信息/用户快照来实现完整信息的展示 如果只存 user_id:
- 每条评论都要 join 用户表
- 或 Redis 查用户信息
- 高并发下存在 N+1 查询问题 评论表中冗余:
user_nickuser_avatarreply_user_nick
| 场景 | 是否更新历史评论 |
|---|---|
| 用户改名 | 不更新 |
| 用户改头像 | 不强制更新 |
| 新评论 | 使用最新信息 |
评论热度排行(Redis ZSet)
排序key设计:comment:hot:{video_id}:
┌────────────┐
│ ZSet │ ← 排序索引
│ comment:hot│
└─────┬──────┘
│ comment_id
┌─────▼──────┐
│ Hash / KV │ ← 评论对象缓存
│ comment:{id}
└─────┬──────┘
│ miss
┌─────▼──────┐
│ MySQL │ ← 事实源
└────────────┘缓存设计
HSET comment:obj:12345
id 12345
root_id 67890
user_nick "张三"
user_avatar "xxx"
content "这视频太牛了"
like_count 23
reply_count 5
created_at 1700000000读评论数据
请求 TopN
→ ZREVRANGE hot_zset
→ Pipeline / Lua 批量取 comment:obj
→ miss 的:
→ 批量 DB
→ 回写 Redis
→ 返回结果| 方案 | 排序 | 展示 | 问题 |
|---|---|---|---|
| ZSet 存完整评论 | 是 | 是 | 内存/更新爆炸 |
| ZSet + DB 回表 | 是 | 否 | DB 压力大 |
| ZSet + KV 缓存 | 是 | 是 | 工业级 |
点赞流程
点赞 → MySQL like_count +1 → ZINCRBY hot_zset → HINCRBY comment:obj:{id} like_count 1
回复流程
回复 → MySQL reply_count +1 → ZINCRBY hot_zset → HINCRBY comment:obj:{id} reply_count 1
四、评论对象缓存 TTL / 淘汰策略
缓存 Key
comment:obj:{comment_id}
TTL 设计(分层)
| 评论类型 | TTL |
|---|---|
| 热评(在 ZSet TopN) | 30 min ~ 2 h |
| 普通评论 | 5 ~ 15 min |
| 冷评论 | 不缓存 / 极短 |
YJ