日期:2026-07-11
标签:#面试 #八股 #系统设计 #点赞 #场景题
一句话答案
点赞系统要同时维护用户与对象的唯一关系和可快速读取的计数,高并发写入可先落 Redis/日志再异步汇总,数据库唯一约束保证最终正确。
面试口语版
核心接口是点赞、取消、查询是否点赞和查询点赞数。关系表以 targetType + targetId + userId 唯一,支持幂等;计数是派生数据,可放 Redis 并异步写数据库。高并发时请求先经过限流,用 Lua 原子修改用户点赞状态和计数,再写 MQ 落关系表;或者先可靠写日志,由流处理聚合。读详情时批量查询用户是否点赞,避免 N+1。热门对象要分桶计数或本地缓存,最终通过关系表重算和对账修正计数。
数据模型
like_relation(target_type, target_id, user_id, status, updated_at)
like_count(target_type, target_id, count, version)
唯一键:(target_type, target_id, user_id)
关键细节
- 点赞和取消是状态设置,不是盲目
+1/-1。 - 展示计数允许短暂最终一致,用户自己的点赞状态通常要求读己之写。
- 防刷包括用户/IP/设备限流、异常频率检测和账号风险。
- 批量列表接口必须批量获取状态和计数。
面试官追问
- Redis 成功但数据库落库失败怎么办?
- 如何避免重复点赞导致计数错误?
- 百万点赞的热门内容如何处理?
面试官追问参考答案
1. Redis 成功但数据库落库失败怎么办?
状态变化必须形成可靠事件,发送失败可通过 Outbox、Redis Stream 或变更日志重试。关系表按唯一键幂等 upsert,定时根据关系明细或事件日志校准计数;不能把一次异步失败当作永久成功。
2. 如何避免重复点赞导致计数错误?
Lua 先检查当前状态,只有从未点赞变为已点赞才加一,从已点赞变为取消才减一。数据库唯一键和状态条件更新再次兜底,所有请求携带业务幂等标识。
3. 百万点赞的热门内容如何处理?
读走多级缓存;单个计数 Key 写热点可按对象和分桶编号拆分,由流处理或读取时聚合。关系明细按 targetId 分片,计数异步合并,展示可容忍秒级延迟并定期校准。
学习清单
- 区分点赞关系与点赞计数。
- 能说明幂等、热点和最终一致性。