评论与互动是微型博客的「社交引擎」:没有评论与点赞,短内容只是一块公告板。但互动系统远比表面复杂——评论树怎么存、点赞计数怎么不丢、转发与回复如何触发通知、刷量与垃圾评论如何拦截,每一个问题都牵扯存储、并发与一致性。
本文系统讲解互动系统的五个核心模块:评论模型、互动类型与计数、互动通知、防滥用、分层存储,并给出从零到生产的工程路径。
一、评论模型
1.1 三种评论形态
| 形态 | 结构 | 适用 | 存储 |
|---|---|---|---|
| 平铺 | 一维列表 | 简单场景 | 单表 + 时间排序 |
| 树形 | 父子嵌套 | 讨论氛围 | 邻接表 / 路径枚举 |
| 热评+平铺 | 热评置顶+其余平铺 | 高流量 | 双查询组合 |
1.2 树形评论的存储
-- 邻接表:parent_id 关联
CREATE TABLE comments (
id BIGINT PRIMARY KEY,
post_id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
parent_id BIGINT DEFAULT NULL, -- 回复对象
root_id BIGINT DEFAULT NULL, -- 顶层评论 id(用于聚合)
content TEXT NOT NULL,
depth INT DEFAULT 0,
created_at TIMESTAMPTZ DEFAULT now(),
status SMALLINT DEFAULT 1 -- 1正常 2删除 3审核中
);
CREATE INDEX idx_comments_post ON comments(post_id, root_id, created_at DESC);
1.3 树形查询
-- 查询某帖全部评论(按 root + created_at 排序,聚合成树)
SELECT * FROM comments
WHERE post_id = :post AND status = 1
ORDER BY root_id, created_at;
-- 应用层组装为树;或直接平铺渲染(Flat 展示 + 缩进)
-- 子评论计数
UPDATE posts
SET comment_count = comment_count + 1
WHERE id = :post;
一句话总结:评论模型的核心是「父子关系怎么存 + 怎么排序展示」——邻接表 + root_id 聚合,能在平铺渲染与树形组装之间自由切换。
二、@提及与回复
2.1 提及解析
用户在评论/帖文中输入 @alice
解析流程:文本扫描 → 匹配 @ + 用户名 → 解析出 user_id 列表
存储:评论内容保留原文 + 附带 mention 数组
通知:向被提及者发送通知
// Go 实现 @ 提及解析
func parseMentions(content string, userRepo UserRepo) ([]uint64, error) {
re := regexp.MustCompile(`@([a-zA-Z0-9_]{2,30})`)
ids := make([]uint64, 0, 2)
for _, m := range re.FindAllStringSubmatch(content, -1) {
uid, err := userRepo.ResolveName(m[1])
if err == nil {
ids = append(ids, uid)
}
}
return ids, nil
}
2.2 回复与通知
A 回复 B 的评论
→ 生成评论(parent_id = B 的评论)
→ 向 B 推送「有人回复了你」
→ 若 @ 了 C,同时通知 C
→ 通知聚合:同一帖多次回复可聚合成一条
2.3 热评置顶
热评算法(简化):
heat = 点赞数 × α + 回复数 × β - 时间衰减 γ
常见实现:Reddit 式热度 = 支持率与时间的组合
热评缓存:posts:id:hot_comments(TTL 5 分钟)
一句话总结:@提及把「社交内容」变成「社交网络」,回复通知与热评置顶则是让讨论「被看见」的两个放大器。
三、互动类型与计数
3.1 互动类型
| 类型 | 语义 | 是否计数 | 是否通知对方 |
|---|---|---|---|
| 点赞 | 认可 | 是 | 可聚合提醒 |
| 转发 | 二次传播 | 是 | 可聚合提醒 |
| 收藏 | 自我留存 | 是 | 否 |
| 关注 | 关系建立 | 否 | 可提醒 |
| 回复 | 讨论 | 是 | 是 |
3.2 互动计数的并发问题
直接 UPDATE posts SET like_count = like_count + 1 在高并发下有丢失更新风险。解法:
// 方案一:Redis 原子自增 + 异步落库
redis.Incr(ctx, "post:123:like")
// 异步任务每 N 秒把增量写回 PostgreSQL
// 方案二:数据库原子更新(单行 UPDATE 天然原子)
UPDATE posts SET like_count = like_count + 1 WHERE id = :post;
// 方案三:计数与明细分离
// 明细表记录谁点了赞;计数表只存累加值,定期重算
3.3 幂等:防止重复点赞
用户重复点击点赞 → 应只记一次
解法:明细表 UNIQUE(user_id, post_id)
点赞 = INSERT ON CONFLICT DO NOTHING
取消 = DELETE
计数 = 明细表 count() 或缓存
3.4 计数一致性兜底
高并发下缓存与 DB 可能偏差
兜底:每日/每小时重算
SELECT post_id, count(*) FROM like_details GROUP BY post_id
写回计数表 → 收敛
一句话总结:互动计数的敌人是「并发丢失更新」与「重复操作」——Redis 原子自增扛峰值、明细表 UNIQUE 保幂等、定期重算收敛偏差,三层配合才能稳。
四、互动聚合与通知
4.1 互动 Feed
把「你的帖文被点赞/转发/回复」聚合成一条流
LikeEvent(post=你的帖, by=张三)
RepostEvent(post=你的帖, by=李四)
→ 聚合为「张三、李四等 5 人赞了你的帖」
→ 展示在通知中心
4.2 聚合规则
同类型同对象 N 分钟内 → 合并一条
例:5 分钟内 5 个赞 → 「张三等 5 人赞了你」
跨类型分开 → 各自独立通知条目
例:赞 1 条 + 回复 1 条 → 两条通知
4.3 通知存储
CREATE TABLE notifications (
id BIGINT PRIMARY KEY,
user_id BIGINT NOT NULL, -- 接收者
actor_ids BIGINT[] DEFAULT '{}', -- 触发者(聚合)
type SMALLINT, -- 1赞 2转发 3回复 4@ 5关注
post_id BIGINT,
comment_id BIGINT,
agg_count INT DEFAULT 1,
is_read BOOLEAN DEFAULT FALSE,
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX idx_notif_user ON notifications(user_id, is_read, created_at DESC);
一句话总结:互动通知的价值在「聚合」——把同对象同类别的 N 条互动折叠成一条有代表性的通知,既减少打扰又保留信息量。
五、防滥用与垃圾互动
5.1 刷量攻击面
- 机器账号批量点赞/转发(刷热度)
- 垃圾评论(广告、引流)
- 恶意 @ 骚扰
- 评论刷屏(低频词重复)
5.2 防护手段
| 手段 | 机制 |
|---|---|
| 速率限制 | 每用户每接口限流(点赞/评论频率) |
| 风控规则 | 新号权重低、异常行为标记 |
| 内容过滤 | 关键词 + 模型识别垃圾评论 |
| 图算法 | 关联账号集群检测(同一设备/同 IP) |
| 人工/仲裁 | 举报 → 审核 → 处理 |
5.3 计数防刷
热度计算时剔除可疑互动
权重化:新号/低信誉账号互动权重 × 0.1
时间窗:短期爆发式互动降权
结果:热度分不受刷量明显影响
一句话总结:防滥用的本质是「识别机器与异常」——限流挡频率、风控挡账号、过滤挡内容、权重挡刷量,四层协同才挡得住规模化攻击。
六、分层存储与性能
6.1 互动数据分层
热数据(Redis):
- 互动计数缓存(like/repost/comment count)
- 热评列表(posts:id:hot_comments TTL 5min)
- 用户是否已赞(post:123:liked:{uid})
持久数据(PostgreSQL):
- 评论明细、点赞明细、转发明细、收藏明细
- 通知表
- 计数表(定时重算落库)
冷数据(归档):
- 超过 N 月的互动明细 → 分区/归档
6.2 高并发写入路径
点赞请求
→ Redis INCR 计数(毫秒级响应)
→ 明细写入队列(异步落库)
→ 通知聚合(异步)
→ 定时任务重算计数并落库
6.3 读写分离
读取评论/互动列表 → 走只读副本
写入互动 → 走主库
计数展示 → 走 Redis 缓存,可短暂延迟
一句话总结:互动系统是典型的「读多写少 + 强展示弱一致」场景——Redis 扛读与瞬时计数、队列削峰异步落库、重算收敛,分层之后并发不再是瓶颈。
七、总结
微型博客互动系统的建设路径可以概括为:先建模、再计数、后聚合、终防护。评论模型用「邻接表 + root_id」支撑树形与平铺双展示;互动计数用「Redis 自增 + 明细 UNIQUE + 定期重算」保证不丢不重;通知用聚合规则把打扰降到最低;防滥用用限流、风控、过滤、权重四层挡住刷量。
互动是微型博客的「生命力」——每一次点赞让创作者得到正反馈,每一次回复让讨论形成社区,每一次转发让内容流动起来。把互动系统做扎实,短内容平台才真正「活」起来。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。