一、业务分析
我们先只考虑点赞计数,可以看到,这个业务的特点是:
-
吞吐量超高,明星一出轨,点赞就爆炸。
-
能够接受一定数据不一致(计数有微小不准确,不是大问题)。
那么,容易想到:
-
单独架一个计数服务,将计数与其他业务逻辑解耦。
-
肯定不能用数据库抗实时读写流量(用MQ异步消费)。
-
Redis天然支持固化,可以用高可用Redis集群来做固化存储。
-
也可以用MySQL来做固化存储,Redis做缓存,读写操作都落缓存,异步线程定期刷DB。
能达到的效果是:
-
服务可以水平扩展。
-
数据量增加时,数据库可以按 msg_id 分库,水平扩展。
-
读写量增加时,缓存也可以水平扩展。
二、计数系统的难点
计数系统的难点,还在于业务的扩展性,以及效率问题。
1、APP首页有多条动态,每条动态都要显示点赞数。
2、同一条动态,不止有点赞数,还有转发数,阅读数,评论数等。
2.1 伪代码
假如用最朴素的方式实现,展示多条动态,多个计数的伪代码如下:
获取首页所有动态id;
for (每一条动态) {
获取阅读计数
获取转发计数
获取评论计数
获取赞计数
}
由于同一个msg_id多了几种计数,Redis 的 key 也需要升级为:
msg_id:read
msg_id:forword
msg_id:comment
msg_id:praise
通过不同的key,存储不同的计数。假设首页有100条动态,每条动态调用4次RPC接口,获取不同的计数,总计要有400次调用,系统的扩展性和效率非常低。
三、系统优化
容易想到的是:增加列,记录更多的计数。
1
这种方式的缺点是:每次要新增一种计数时,就要修改表结构,比较麻烦。那能不能不变更表的结构呢?可以,行扩展是更好的方式。
2
表结构固化为:(msg_id, count_key, count_value)
。当要扩充业务计数时,增加一行就行,不需要修改表结构。接下来看下redis的优化方案:
四、总结
-
服务化,计数系统与业务系统解耦。
-
用缓存扛实时读写,数据库和缓存水平切分扩展。
-
数据库使用行扩展,如果有需要缓存可以用一个value存储多个业务计数(
key:100:200:300:200
)。
网友评论