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


其次 , 信息流未读数请求量极大、并发极高 , 这是因为接口是客户端轮询请求的 , 不是用户触发的 。也就是说 , 用户即使打开微博客户端什么都不做 , 这个接口也会被请求到 。在几年前 , 请求未读数接口的量级就已经接近每秒 50 万次 , 这几年随着微博量级的增长 , 请求量也变得更高 。而作为微博的非核心接口 , 我们不太可能使用大量的机器来抗未读数请求 , 因此 , 如何使用有限的资源来支撑如此高的流量是这个方案的难点 。
最后 , 它不像系统通知那样有共享的存储 , 因为每个人关注的人不同 , 信息流的列表也就不同 , 所以也就没办法采用系统通知未读数的方案 。
那要如何设计能够承接每秒几十万次请求的信息流未读数系统呢?你可以这样做:首先 , 在通用计数器中记录每一个用户发布的博文数;然后在 Redis 或者中记录一个人所有关注人的博文数快照 , 当用户点击未读消息重置未读数为 0 时 , 将他关注所有人的博文数刷新到快照中;这样 , 他关注所有人的博文总数减去快照中的博文总数就是他的信息流未读数
假如用户 A , 像上图这样关注了用户 B、C、D , 其中 B 发布的博文数是 10 , C 发布的博文数是 8 , D 发布的博文数是 14 , 而在用户 A 最近一次查看未读消息时 , 记录在快照中的这三个用户的博文数分别是 6、7、12 , 因此用户 A 的未读数就是(10-6)+(8-7)+(14-12)=7 。这个方案设计简单 , 并且是全内存操作 , 性能足够好 , 能够支撑比较高的并发 , 事实上微博团队仅仅用 16 台普通的服务器就支撑了每秒接近 50 万次的请求 , 这就足以证明这个方案的性能有多出色 , 因此 , 它完全能够满足信息流未读数的需求 。
当然了这个方案也有一些缺陷 , 比如说快照中需要存储关注关系 , 如果关注关系变更的时候更新不及时 , 那么就会造成未读数不准确;快照采用的是全缓存存储 , 如果缓存满了就会剔除一些数据 , 那么被剔除用户的未读数就变为 0 了 。但是好在用户对于未读数的准确度要求不高(未读 10 条还是 11 条 , 其实用户有时候看不出来) , 因此 , 这些缺陷也是可以接受的 。
通过分享未读数系统设计这个案例 , 我想给你一些建议:
小结
本节课我们了解了未读数系统的设计 , 这里你需要了解的重点是:
这里你可以看到 , 这三类需求虽然都和未读数有关 , 但是需求场景不同、对于量级的要求不同 , 设计出来的方案也就不同 。因此 , 就像我刚刚提到的样子 , 你在做方案设计的时候 , 要分析需求的场景 , 比如说数据的量级是怎样的 , 请求的量级是怎样的 , 有没有一些可以利用的特点(比如系统通知未读场景下的有限共享存储、信息流未读场景下关注人数是有限的等等) , 然后再制定针对性的方案 , 切忌盲目使用之前的经验套用不同的场景 , 否则就可能造成性能的下降 , 甚至危害系统的稳定性 。