高并发系统架构设计之实战篇35:计数系统设计之未读数系统( 二 )


另外 , 使用这种方式需要给系统中的每一个用户都记一个未读数的值 , 而在系统中 , 活跃用户只是很少的一部分 , 大部分的用户是不活跃的 , 甚至从来没有打开过系统通知 , 为这些用户记录未读数显然是一种浪费 。
通过上面的内容 , 你可以知道为什么我们不能用通用计数系统实现系统通知未读数了吧?那正确的做法是什么呢?要知道 , 系统通知实际上是存储在一个大的列表中的 , 这个列表对所有用户共享 , 也就是所有人看到的都是同一份系统通知的数据 。不过不同的人最近看到的消息不同 , 所以每个人会有不同的未读数 。因此 , 你可以记录一下在这个列表中每个人看过最后一条消息的 ID , 然后统计这个 ID 之后有多少条消息 , 这就是未读数了 。
这个方案在实现时有这样几个关键点:
这是一种比较通用的方案 , 即节省内存 , 又能尽量减少获取未读数的延迟 。这个方案适用的另一个业务场景是全量用户打点的场景 , 比如像下面这张微博截图中的红点 。
这个红点和系统通知类似 , 也是一种通知全量用户的手段 , 如果逐个通知用户 , 延迟也是无法接受的 。因此你可以采用和系统通知类似的方案 。首先 , 我们为每一个用户存储一个时间戳 , 代表最近点过这个红点的时间 , 用户点了红点 , 就把这个时间戳设置为当前时间;然后 , 我们也记录一个全局的时间戳 , 这个时间戳标识最新的一次打点时间 , 如果你在后台操作给全体用户打点 , 就更新这个时间戳为当前时间 。而我们在判断是否需要展示红点时 , 只需要判断用户的时间戳和全局时间戳的大小 , 如果用户时间戳小于全局时间戳 , 代表在用户最后一次点击红点之后又有新的红点推送 , 那么就要展示红点 , 反之 , 就不展示红点了 。
这两个场景的共性是全部用户共享一份有限的存储数据 , 每个人只记录自己在这份存储中的偏移量 , 就可以得到未读数了 。你可以看到 , 系统消息未读的实现方案不是很复杂 , 它通过设计避免了操作全量数据未读数 , 如果你的系统中有这种打红点的需求 , 那我建议你可以结合实际工作灵活使用上述方案 。
最后一个需求关注的是微博信息流的未读数 , 在现在的社交系统中 , 关注关系已经成为标配的功能 , 而基于关注关系的信息流也是一种非常重要的信息聚合方式 , 因此 , 如何设计信息流的未读数系统就成了你必须面对的一个问题 。
二、未读数设计方案

高并发系统架构设计之实战篇35:计数系统设计之未读数系统

文章插图
信息流的未读数之所以复杂主要有这样几点原因 。
首先 , 微博的信息流是基于关注关系的 , 未读数也是基于关注关系的 , 就是说 , 你关注的人发布了新的微博 , 那么你作为粉丝未读数就要增加 1 。如果微博用户都是像我这样只有几百粉丝的“小透明”就简单了 , 你发微博的时候系统给你粉丝的未读数增加 1 不是什么难事儿 。但是对于一些动辄几千万甚至上亿粉丝的微博大 V 就麻烦了 , 增加未读数可能需要几个小时 。假设你是杨幂的粉丝 , 想了解她实时发布的博文 , 那么如果当她发布博文几个小时之后 , 你才收到提醒 , 这显然是不能接受的 。所以未读数的延迟是你在设计方案时首先要考虑的内容 。