[编程技术] 点赞和评论 技术设计与实现
作者:CC下载站 日期:2021-01-22 13:00:51 浏览:17 分类:编程开发
上篇文章介绍了朋友圈的技术设计,这篇将介绍朋友圈点赞和评论的实现方式。
需求介绍
- 对某条状态实现点赞与取消点赞的功能。
- 点赞列表按时间从小到大排序。
- 点赞列表支持分页查询。
- 对某条状态实现评论和删除评论的功能。
- 评论列表按时间从小到大排序。
- 评论列表支持分页查询。
技术分析
原始方案
由于评论和点赞的数据量可能非常大,所以一开始用了缓存来降低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
取消回复欢迎 你 发表评论:
- 精品推荐!
-
- 最新文章
- 热门文章
- 热评文章
[资料] 【2024年军队文职公共科目/专业课/真题及押题卷】
[少儿教育] 唐诗三百首微电影(全314集)·少儿学唐诗
[资料] 2025军队文职 公共课+专业课+真题+押题+面试【合集】
[课程] 《大师级航拍教程》63节课程视频 MP4格式 5.9G
[资料] 中医鬼才倪海厦全集完整版+资料全集
[课程] 聂佳判断推理绝版课程大集合【8G】
[电视剧] 芈月传 【全集81集全】【未删减版】【国语中字】【2015】【HD720P】【75G】
[电视剧] 封神榜 梁丽版 (1989) 共5集 480P国语无字 最贴近原著的一版【0.98 G】
[影视] 【雪山飞孤4个版本】【1985、1991、1999、2007】【1080P、720P】【中文字幕】【167.1G】
[资料] 24秋初中改版教材全集(全版本)[PDF]
[书籍] 彭子益医书合集 [PDF/DOC]
[游戏] 《黑神话悟空》免安装学习版【全dlc整合完整版】+Steam游戏解锁+游戏修改工具!
[动画] 《名侦探柯南》名侦探柯南百万美元的五菱星 [TC] [MP4]
[动画] 2002《火影忍者》720集全【4K典藏版】+11部剧场版+OVA+漫画 内嵌简日字幕
[剧集] 《斯巴达克斯》1-4季合集 无删减版 1080P 内嵌简英特效字幕
[CG剧情] 《黑神话:悟空》158分钟CG完整剧情合集 4K120帧最高画质
[游戏] 黑神话悟空离线完整版+修改器
[电影] 《变形金刚系列》七部合集 [4K HDR 蓝光] 国英双语音轨 [内封精品特效字幕]【典藏版】235G
[动画] 西游记 (1999) 动画版 4K 全52集 高清修复版 童年回忆
[图像处理] 光影魔术手v4.6.0.578绿色版
[影视] 美国内战 4K蓝光原盘下载+高清MKV版/内战/帝国浩劫:美国内战(台)/美帝崩裂(港) 2024 Civil War 63.86G
[影视] 一命 3D 蓝光高清MKV版/切腹 / 切腹:武士之死 / Hara-Kiri: Death of a Samurai / Ichimei 2011 一命 13.6G
[影视] 爱情我你他 蓝光原盘下载+高清MKV版/你、我、他她他 2005 Me and You and Everyone We Know 23.2G
[影视] 穿越美国 蓝光原盘下载+高清MKV版/窈窕老爸 / 寻找他妈…的故事 2005 Transamerica 20.8G
[电影] 《黄飞鸿》全系列合集
[Android] 开罗游戏 ▎像素风格的模拟经营的游戏厂商安卓游戏大合集
[游戏合集] 要战便战 v0.9.107 免安装绿色中文版
[书籍] 彭子益医书合集 [PDF/DOC]
[系统]【黑果小兵】macOS Big Sur 11.0.1 20B50 正式版 with Clover 5126 黑苹果系统镜像下载
[美图] 【经典收藏美图集合】1500多张韩国美女高清图片让你的收藏夹更加丰富多彩
- 最新评论
-
找了好久的资源,终于在这里找到了。感谢本站的资源和分享。谢谢285552528 评论于:11-09 找了好久的资源bjzchzch12 评论于:11-07 谢谢分享感谢ppy2016 评论于:11-05 谢谢分享感谢ppy2016 评论于:11-05 有靳东!嘻嘻奥古斯都.凯撒 评论于:10-28 流星花园是F4处女作也是4人集体搭配的唯一一部!奥古斯都.凯撒 评论于:10-28 找了好久的资源,终于在这里找到了。感谢本站的资源和分享。谢谢AAAAA 评论于:10-26 找了好久的资源,终于在这里找到了。感谢本站的资源和分享。谢谢password63 评论于:10-26 找了好久的资源,终于在这里找齐了!!!!blog001 评论于:10-21 找了好久的资源,终于在这里找齐了!!!!blog001 评论于:10-21
- 热门tag