每秒30W次的点赞业务,怎么优化?

简介: 30WQPS的点赞计数业务,如何设计?

image.png

继续答星球水友提问,30WQPS的点赞计数业务,如何设计? 可以看到,这个业务的特点是:(1)吞吐量超高;(2)能够接受一定数据不一致;画外音:计数有微小不准确,不是大问题。 先用最朴素的思想,只考虑点赞计数,可以怎么做?有几点是最容易想到的:(1)肯定不能用数据库抗实时读写流量;(2)redis天然支持固化,可以用高可用redis集群来做固化存储;(3)也可以用MySQL来做固化存储,redis做缓存,读写操作都落缓存,异步线程定期刷DB;(4)架一层计数服务,将计数与业务逻辑解耦; 此时MySQL核心数据结构是:

t_count(msg_id, praise_count)

  此时redis的KV设计也不难:

key:msg_id

value:praise_count
image.png

似乎很容易就搞定了:(1)服务可以水平扩展;(2)数据量增加时,数据库可以水平扩展;(3)读写量增加时,缓存也可以水平扩展; 计数系统的难点,还在于业务扩展性问题,以及效率问题。 以微博为例:
image.png

(1)用户微博首页,有多条消息list<msg_id>,这是一种扩展;(2)同一条消息msg_id,不止有点赞计数,还有阅读计数,转发计数,评论计数,这也是一种扩展; 假如用最朴素的方式实现,多条消息多个计数的获取伪代码如下:

// (1)获取首页所有消息msg_id

list<msg_id> = getHomePageMsg(uid);

// (2)对于首页的所有消息要拉取多个计数

for( msg_id in list<msg_id>){

         //(3.1)获取阅读计数

         getReadCount(msg_id); 

         //(3.2)获取转发计数

         getForwordCount(msg_id);

         //(3.3)获取评论计数

         getCommentCount(msg_id);

         //(3.4)获取赞计数

         getPraiseCount(msg_id);

}

  由于同一个msg_id多了几种业务计数, redis的key需要带上业务flag ,升级为:

msg_id:read

msg_id:forword

msg_id:comment

msg_id:praise

用来区分共一个msg_id的四种不同业务计数,redis不能支持key的模糊操作,必须访问四次reids。   假设首页有100条消息,这个方案总结为: (1)for循环每一条消息,100条消息100次; (2)每条消息4次RPC获取计数接口调用; (3)每次调用服务要访问reids,拼装key获取count; 画外音:这种方案的扩展性和效率是非常低的。   那如何进行优化呢?   首先看下数据库层面元数据扩展,常见的扩展方式是, 增加列 ,记录更多的业务计数。
image.png

如上图所示,由一列点赞计数,扩充为四列阅读、转发、评论、点赞计数。

  增加列这种业务计数扩展方式的缺点是: 每次要扩充业务计数时,总是需要修改表结构 ,增加列,很烦。   有没有不需要变更表结构的扩展方式呢? 行扩展 是一种扩展性更好的方式。
image.png

表结构固化为:

t_count(msg_id, count_key, count_value)

当要扩充业务计数时,增加一行就行,不需要修改表结构。 画外音:很多配置业务,会使用这种方案,方便增加配置。   增加行这种业务计数扩展方式的缺点是: 表数据行数会增加 ,但这不是主要矛盾,数据库水平扩展能很轻松解决数据量大的问题。   接下来看下redis批量获取计数的优化方案。
image.png

原始方案,通过拼装key来区分同一个msg_id的不同业务计数。

  可以升级为,同一个value来存储多个计数。
image.png

如上图所示,

同一个msg_id的四个计数 ,存储在一个value里,从而避免多次redis访问。
画外音:通过value来扩展,是不是很巧妙?   总结 计数业务,在数据量大,并发量大的时候,要考虑的一些技术点: (1)用缓存抗读写; (2)服务化,计数系统与业务系统解耦; (3)水平切分扩展吞吐量、数据量、读写量; (4)要考虑扩展性,数据库层面常见的优化有:列扩展,行扩展两种方式; (5)要考虑批量操作,缓存层面常见的优化有:一个value存储多个业务计数;   计数系统优化先聊到这里,希望大家有收获。

欢迎大家继续提问,有问必答。

本文转自“架构师之路”公众号,58沈剑提供。

目录
相关文章
|
NoSQL 安全 Go
Golang 官方推荐使用的 Redis 客户端 redigo
Golang 官方推荐使用的 Redis 客户端 redigo
698 0
|
7月前
|
存储 人工智能 监控
CoPaw是什么?与OpenClaw有什么区别?
2026年个人智能体爆发,阿里云CoPaw与开源OpenClaw成焦点。前者主打“协同工作台”,支持一键部署、长期记忆与开箱即用技能,面向职场人;后者是极客向AI实验平台,强调本地优先与高度定制。二者代表便捷性与自由度的路线之争。
5007 11
|
NoSQL Java 关系型数据库
这个评论系统设计碉堡了
先赞后看,南哥助你Java进阶一大半官网给出了Facebook评论系统的高级设计图,Facebook的评论竟然是支持实时刷新的。也就是说用户不用刷新帖子,只要帖子有新的评论就会自动推送到用户端,这里Facebook使用的便是每天在全球有设备在使用的WebSocket技术。我是南哥,一个Java学习与进阶的领路人。相信对你通关面试、拿下Offer进入心心念念的公司有所帮助。
1163 5
这个评论系统设计碉堡了
|
SQL 中间件 关系型数据库
那些年,我们在Go中间件上踩过的坑
作者总结了过去在Go中间件上踩过的坑,这些坑也促进了阿里内部Go中间件的完善,希望大家学习本文后,不犯同样的错误。
|
小程序 物联网 Java
Android 蓝牙BLE开发从官方源码demo开始(一)
Android 蓝牙BLE开发从官方源码demo开始(一)
|
存储 自然语言处理 NoSQL
深入解析Elasticsearch的内部数据结构和机制:行存储、列存储与倒排索引之倒排索引(三)
深入解析Elasticsearch的内部数据结构和机制:行存储、列存储与倒排索引之倒排索引(三)
|
存储 网络协议 Linux
在Linux中,如何通过syslog进行远程日志转发?
在Linux中,如何通过syslog进行远程日志转发?
|
Android开发 Windows
Mac 好用的 Android 模拟器整理(玩游戏、装应用、支持咸鱼、拼多多...)
Mac 好用的 Android 模拟器整理(玩游戏、装应用、支持咸鱼、拼多多...)
27599 47
|
数据可视化 数据挖掘 Go
RNA-seq丨转录组分析标准流程与常用工具
RNA-seq丨转录组分析标准流程与常用工具

热门文章

最新文章