[编程技术] 点赞和评论 技术设计与实现
作者:CC下载站 日期:2021-01-22 13:00:51 浏览:4 分类:编程开发
上篇文章介绍了朋友圈的技术设计,这篇将介绍朋友圈点赞和评论的实现方式。
需求介绍
- 对某条状态实现点赞与取消点赞的功能。
- 点赞列表按时间从小到大排序。
- 点赞列表支持分页查询。
- 对某条状态实现评论和删除评论的功能。
- 评论列表按时间从小到大排序。
- 评论列表支持分页查询。
技术分析
原始方案
由于评论和点赞的数据量可能非常大,所以一开始用了缓存来降低DB的查询频率。 Cache更新策略采用了监听MySQL的Binlog来更新Cache的方式,而不是应用层在写DB的时候同步写Cache的方式。 因为这样可以把DB写入和Cache写入解耦,应用层只用关注DB的写入,把Cache当作DB的一个Slave一样同步更新。
由于点赞和评论系统基本一致,评论会稍微略复杂,因为多了一个评论内容。这里就以评论系统为例,看一下整个系统如何设计。
定义结构
首先看一下数据储存格式:
1
2
3
4
5
6
7
8
9
CREATE TABLE `comment_tab` (
`comment_id` bigint(20) unsigned NOT NULL,
`userid` bigint(20) unsigned NOT NULL,
`activity_id` bigint(20) unsigned NOT NULL,
`comment` varchar(1024) NOT NULL,
`update_time` int(11) NOT NULL COMMENT 'update time',
PRIMARY KEY (`comment_id`),
KEY `idx_activity_id` (`activity_id`, `update_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
并定义了protobuf映射comment_tab的一行数据。
1
2
3
4
5
6
7
8
//protobuf类型,序列化
message CommentData {
optional int64 comment_id = 1; //unique id
optional int64 userid = 2; //the userid who comment to this activity
optional int64 activity_id = 3; // the activity id you comment
optional string comment = 4; //the real comment text
optional int32 update_time = 5; // the comment timestamp(second)
}
需求分析
- 获取评论列表,支持分页。
Request:
activity_id,
cursor, //cursor默认为0,下次请求的cursor为上次返回的cursor以便可以分页向后查找。
limit, //每次查询的次数。
Response:
Array of CommentData
cursor
- 增加评论。
- 删除评论。
解释一下上图的缓存设计,这里设计了两层Cache。
Memcached
Key: comment_id
Value: Marshal(CommentData)
代表的是某一条Comment数据的序列化。
Redis ZSet
Key: activity_id
-- member: comment_id
-- score: update_time
代表的是某一条activity_id所有的comment,按score(update_time)排序。可以很方便的支持分页。
我们的DB使用了TiDB,兼容绝大部分MySQL语法,是分布式的数据库,数据量大的时候使用TiDB更加高校,可以支持方便扩容。 但是跟DBA讨论之后,DBA不赞同这种实现方式,他们认为社交场景下流量峰值是不可控的,比如微博热门事件经常会导致服务不可用。
- 直接同步写DB会导致DB压力会非常大,他们建议我们使用内存数据库作为真实数据源,并且异步备份存到TiDB上,这样DB的写入QPS可控。所有读的流量只经过内存数据库(Redis)而不经过TiDB。
- TiDB的Binlog不稳定,不建议使用。(原因? TiDB binglog )。
进阶方案
此方案下我们使用Redis的持久化模式作为数据源,然后异步备份到TiDB。
此方案使用了异步写入DB的方式,可以流量消峰,应用层使用Redis来服务用户,并使用Redis的String类型代替Memcached(因为Memcached不支持持久化), Redis作为内存数据库,查询速度非常快。 只是在数据量非常大的情况下,需要申请非常多的内存资源。
在这里我们需要两种类型的数据来储存评论的数据。
Redis String
Key: comment_id; Value: proto.Marshal(CommentData)
Redis ZSet
Key: activity_id; – member: userid; – score: update_time;
比如每次查询limit=100, 那我想要查询下100个怎么办呢,需要把上次返回的最后一个的score作为cursor返回,这样下次查询带着这个cursor查找。 因为ZRevRangeByScore以及其他类似的Cmd都是支持Max,Min,Limit等查询参数的。 在这里,Max: “(curosr”, Limit: “100”.
问题总结
到这里已经有一个相对完整的技术方案了,但是这个方案还有一些问题。
- 使用update_time作为score, 由于update_time是second级别,有很大的概率重复(多个用户同时评论同一个activity_id). 这会导致分页查询的时候会导致数据数据重复或者遗漏。(因为我们比较的时候是用大小比较的)。 这有人就问了,为什么不直接用Offset和Limit呢,这样每次直接从指定位置查询。不用管score的大小,重复也没关系。 这种方案会有两种问题:
- 如果你分页向下查找的过程中,有了一条新的评论。比如你第一次取了1-100,第二次取101-200,在你第一二次之间有一个新的评论进来,由于它是最新的,会变成1号评论,所有其他的评论都会下降1位,导致你第二次取101-200中的101是上次的100. 导致重复。使用cursor使用score比较的,不会出现这个问题。
- 拉取列表的时候,有可能有一些过滤条件,比如,只有你的好友的评论才能展示,那有些评论可能就需要过滤掉。你只显示了100条,但是实际上可能在Redis里面查询了351条。下次需要从352条开始查。你怎么把offset=101根352映射起来呢。
所以我们才用了cursor的方式,无论是查询DB还是查询Redis都是一种比Offset更好的解决方案。可能他的缺点就是规则要固定,不能这次我用update_time排序,下次我用userid排序这种情况。
使用cursor怎么解决这种情况呢,有人可能会说,可以把timestamp改为int64的nanosecond啊,这种方案跟我们下面的方案有着同样的问题。
我根据snowflake算法把update_time变成一个int64的唯一的随update_time递增的ID。 snowflake算法介绍如下: snowflake 心想,这样终于能解决问题了吧,cursor变成了唯一的值,每次使用上次返回的最后一个cursor来查询下次的分页数据,应该不会重复了吧。 然后问题又出现了,依然出现了重复。 查看Redis ZSet数据如图: 最后在Redis的官方文档上发现了以下的话。
Range of integer scores that can be expressed precisely
Redis sorted sets use a double 64-bit floating point number to represent the score. In all the architectures we support, this is represented as an IEEE 754 floating point number, that is able to represent precisely integer numbers between -(2^53) and +(2^53) included. In more practical terms, all the integers between -9007199254740992 and 9007199254740992 are perfectly representable. Larger integers, or fractions, are internally represented in exponential form, so it is possible that you get only an approximation of the decimal number, or of the very big integer, that you set as score
是的,score采用了 double 64-bit floating point number. 支持的int最大值是(2^53-1) 所以我改造了以下snowflake算法。 Redis ZSET问题分析及解决方案
- 另外,由于前端调用我们的借口使用了json的序列化方式。 可以看到JavaScript同样使用了IEEE 754,也就是说也只是支持到(2^53-1)的最大值。
Javascript Number.MAX_SAFE_INTEGER 所以大于(2^53-1)的数是不能正常的序列化和反序列化的。
数据一致性
我们先保证了Redis数据更新成功,然后使用MQ异步写入TiDB,怎么保证Redis数据和TiDB的数据的一致性呢。 进阶方案好像并没有使用TiDB,那把数据写入TiDB有什么用呢。
- 以防Redis故障可以从TiDB导入数据。
- TiDB数据方便做数据分析和统计。
<全文完>
猜你还喜欢
- 03-29 [编程相关] Winform窗体圆角以及描边完美解决方案
- 03-29 [前端问题] has been blocked by CORS policy跨域问题解决
- 03-29 [编程相关] GitHub Actions 入门教程
- 03-29 [编程探讨] CSS Grid 网格布局教程
- 10-12 [编程相关] python实现文件夹所有文件编码从GBK转为UTF8
- 10-11 [编程算法] opencv之霍夫变换:圆
- 10-11 [编程算法] OpenCV Camshift算法+目标跟踪源码
- 10-11 [Python] python 创建 Telnet 客户端
- 10-11 [编程相关] Python 基于 Yolov8 + CPU 实现物体检测
- 03-15 [脚本工具] 使用go语言开发自动化脚本 - 一键定场、抢购、预约、捡漏
- 01-08 [编程技术] 秒杀面试官系列 - Redis zset底层是怎么实现的
- 01-05 [编程技术] 《Redis设计与实现》pdf
取消回复欢迎 你 发表评论:
- 精品推荐!
-
- 最新文章
- 热门文章
- 热评文章
[课程] 极客时间-从 0 开发一款 iOS App
[网赚相关] 最新网易云梯计划网页版,单机月收入5000+!!
[摄影] 玩转手机摄影 | 滤镜手机支架
[美食] 春天最不能忘记吃的菜,脆甜爽口营养高,减肥、控糖都很合适
[美食] “湿气”最怕这种菜,三天两头吃一次!祛湿健脾一身轻,别不懂吃
[影视资讯] 2023-2025年所有“漫威电影和剧集”上映播出时间整理
[经验] 摆地摊的八大禁忌
[网赚相关] 2024抖音_不违法不下单_0投入维权_打假详细教程
[海报素材] 2024年五一国际劳动节海报素材合集
[课程] Kali安全渗透+Web白帽子高级工程师+黑客攻防 - 带源码课件
[资料] [大学期末救急课] 猴博士+高斯课堂+斐多课堂,全集视频合集
[云资源] 价值2万元的老男孩Python教程
[书库] 史上最全摄影书推荐(附700本PDF版打包下载)
[云资源] 花了一千多元买的私人健身教程
[下载工具] Internet Download Manager 6.42.7 (IDM)
[影视] 灌篮高手 WEB-DL版下载/Slam Dunk/スラムダンク/灌篮高手:THE FIRST/灌篮高手电影版 2022 The First Slam Dunk 61.35G
[即时通讯] 腾讯QQ PC版9.7.22.29315去广告绿色纯净版
[开发环境] PhpStorm2023中文激活版v2023.3.3 正式版
[资料] 3000 套电影电视剧 LOGO 宣传片常用音效合集包
[安卓软件] 酷我音乐APP_v10.7.6.4 去广告破解豪华VIP版
[云资源] 价值2万元的老男孩Python教程
[影视] 灌篮高手 WEB-DL版下载/Slam Dunk/スラムダンク/灌篮高手:THE FIRST/灌篮高手电影版 2022 The First Slam Dunk 61.35G
[云资源] 花了一千多元买的私人健身教程
[书库] 史上最全摄影书推荐(附700本PDF版打包下载)
[动画] 北斗神拳(1984) [两季合集] [MKV]
[资料] 抗战阵亡将士资料+续编
[电视剧] 三体 (2024) 全8集 网飞版本 中文字幕 合集
[影视] 三大队 WEB-DL版下载/Endless Journey/请转告局长,三大队任务完成了 2023 三大队 6.7G
[纪录片] 河西走廊【10集 国语 中文字幕 1080P 10.8G MP4】
[安卓软件] OfficeSuite中文版APP v14.2.50872.0破解版
- 最新评论
-
我想看看mw2ddyy 评论于:04-26 好东西阿zfy123123 评论于:04-18 谢谢楼主xiaoqi 评论于:04-12 勿在线解压,勿手机解压,请在电脑上用最新款压缩软件解压!推荐360压缩或者好压CC下载站 评论于:04-10 无法解压啊,客服能不能给个解压教程ravengrey 评论于:04-10 谢谢支持!!CC下载站 评论于:03-26 很棒的资源,感谢分享云体风身 评论于:03-26 感谢分享,好东西云体风身 评论于:03-26 谢谢支持!CC下载站 评论于:03-14 央视精品,感谢付出提供。qwer9009 评论于:03-14
- 热门tag