这是 Beta 探索课程,内容结构、实验步骤和示例可能会继续调整。
未读数量优化
未读数为什么难
老王问:「未读数量查询会不会很慢?」
数据量:
insite_messages 表:
- 总消息数:500 万条
- 每用户平均:100 条
- 每用户未读:10 条
未读数量查询是高频操作,每次打开 App 都要查。如果每次都 COUNT(*) WHERE is_read = 0,会在大表上反复全扫。
方案 A:Redis 缓存
- 未读数存 Redis,读取快。
- 问题:缓存过期 / 不一致时数字不准,需要兜底。
方案 B:独立计数表
新建 user_unread_counts:
| 字段 | 含义 |
|---|---|
| user_id | 用户 |
| type | 通知类型 |
| count | 未读数 |
每次创建 / 标记已读时,更新计数:
创建消息:INSERT 消息 + UPDATE 计数 +1
标记已读:UPDATE 消息 + UPDATE 计数 -1
未读计数的更新流程
业务事件(新评论 / 点赞)
写入消息 + 计数 +1(同一事务)
步骤 1 · 动作保证一致性打开 App 读取计数表
步骤 2 · 动作毫秒级,不 COUNT 大表标记已读 + 计数 -1
步骤 3 · 动作同步给其他设备定期对账
步骤 4 · 判断纠正常见偏差未读数准确、读取快
为什么选方案 B
我选择了独立计数表,因为:
- 计数准确:不依赖缓存过期。
- 按类型统计:可分别统计评论未读 3 条、点赞未读 5 条。
- 性能好:更新时只需一条 SQL。
计数一致性的注意点
- 消息创建与计数更新要在同一事务,避免不一致。
- 定期对账:扫描
is_read与计数表,纠正常见的偏差。 - 类型维度:计数的粒度和业务查询一致。
一句话
未读数优化 = 独立计数表 + 事务一致性 + 定期对账。用「预聚合的计数」替代「每次 COUNT」,是高频查询的标准解法。
发现内容有问题?
告诉我们哪里需要改进。
