当前位置: 首页 > news >正文

高并发系统设计 --基于MySQL构建评论系统

如何用MySQL来实现评论系统

为什么我不用mongodb?

  1. 社区成熟度不如MySQL,redis
  2. 需要学习的东西很多,迁移,扩容,片建,集群
  3. redis > mongodb

架构设计

使用MySQL进行存储的话,就必须要用到Redis来做缓存,后台admin需要接通ES来进行查询,comment-service通过异步来进行写Redis和MySQL评论数据,MySQL和ES通过Canal进行binlog同步。

缓存模式

首先我们需要预读,我们读第一页的时候,也需要把第二页的内容加载出来。读第二页的时候,我们预先读第三页,这样可以避免大量的cache miss。

但是这里有一个致命的问题就是:当缓存抖动的时候,会触发大量的cache rebuild,因为我们使用了预加载,容易造成OOM(内存溢出)。因此我们需要使用消息队列来进行逻辑异步化,对于当前请求,只返回MySQL中的部分数据即可。

写的逻辑

至于写的操作,我们要穿透到存储层,因此最好使用消息队列异步削峰。例如我的评论发布出去了,用户过100ms才看到评论,这是无所谓的。

存储设计

comment_subject表

idint主键
obj_idint对象id
obj_typeint对象类型
member_idint作者id
countint评论总数
root_countint跟评总数
all_countint评论+回复总数
stateint状态 0:正常 1:隐藏
attrsint属性 0:置顶 1:不置顶
create_time+update_timedatatime创建时间,修改时间

obj_id+obj_type把评论系统设计成中台。 一般是指搭建一个灵活快速应对变化的架构,快速实现前端提的需求,避免重复建设,达到提高工作效率目的。

obj_id+obj_type形成了一个业务键,比如微博,发帖,发视频,你可以发视频,你也可以发文章,评论系统设计成中台。

comment_index

idint主键id
obj_idint对象id
obj_typeint对象类型
member_idint发表者id
rootint根评论id,不为0是回复评论
parentint父评论id,为0是root评论
floorint评论楼层
countint评论总数
root_countint根评论总数
likeint点赞数
hateint点踩数
stateint状态,0:正常;1:隐藏
attrsint属性
create_timedatetime创建时间
update_timedatetime修改时间

parent:父评论id,其实就是记录是否是回复评论。

comment_content表:

comment_idint主键
at_member_idsvarchar对象id
ipint对象类型
platformint发表者id
devicevarchar跟评论id,不为0是回复评论
messagevarchar评论内容
metavarchar评论元数据:背景,字体
create_timedatetime创建时间
update_timedatetime修改时间

index是索引表,content是内容表。

数据写入:事务更新comment_subjectcomment_indexcomment_content三张表,其中content是非强制性需要一致性考虑的。因此可以先写入content,之后事务更新其他表。即便content更新成功,后续失败仅仅存在一条ghost数据。

数据读取:基于obj_id + obj_typecomment_index表找到评论列表,where root=0 order by floor。之后根据comment_index的id字段捞出comment_content的评论内容。对于二级的子楼层,where parent/root in(id...)

为什么要把index和content分成两个表

comment_index:评论楼层的索引表,实际并不包含内容。comment_content:评论内容的表,包含评论的具体内容。其中comment_index的id字段和comment_content是1对1的关系,这里面包含了几种设计思想。

  • 表都有主键,comment_content没有id,是为了减少一次二级索引查找,直接基于主键检索,同时comment_id在写入要尽可能的顺序自增。
  • 索引,内容分离,方便mysql_datapage缓存更多的row,如果和content耦合,会导致更大的IO。长远来看content信息可以直接使用KV storage存储。

缓存设计

comment_subject_cache【string】

keystringoid_type
valueintsubject marshal string
expireduration24h

comment_index_cache【sorted set】

keystringcache key:oid_type_sort其中sort为排序方式,0:楼层,1:回复数量
memberintcomment_id:评论id
scoredouble楼层号,回复数量,排序得分
expireduration8h

comment_content_cache

keystringcomment_id
valueintcontent
expireduration24h

comment_subject_cache:对应主题的缓存,value使用protobuf序列化的方式存入,这样调用rpc的时候速度可以更块一点。

comment_index_cache:使用redis sorted set进行索引的缓存,索引即数据的组织顺序,而非数据内容。通过预加载少量数据,通过增量加载的方式逐渐预热填充缓存,而redis sorted set skiplist的实现可以做到O(logN) + O(M)的时间复杂度,效率很高

sorted set是要增量追加的,因此必须判定key存在,才能zadd

comment_content_cache:对应评论内容数据,使用protobuf序列化的方式存入。

增量加载(目标表仅更新源数据表中变化的内容)+lazy加载(延迟加载,种将资源标识为非阻塞(非关键)资源并仅在需要时加载它们的策略)

可用性设计

其实就是各种缓存问题,消息队列消息等问题。

如果这个key是热点的key的话可以使用本地缓存+分布式缓存。

那么如何统计是否是热点呢?

这里,我们就移步到我们的下一篇文章了,谢谢大家。

相关文章:

  • 游戏发卡中心网站源码/谷歌外贸平台推广需要多少钱
  • 字体 wordpress/收录好的网站有哪些
  • 内蒙古通辽网站建设/百度推广自己怎么做
  • 旅游电子商务网站建设/广州seo成功案例
  • 在线生成固定悬浮导航的工具网站/b站暴躁姐
  • 西宁市建设网站多少钱/搜索引擎营销的优势和劣势
  • 【Javascript】面向对象编程,this,原型与原型链,类与实例
  • 10.2 初始泛型算法
  • 卡方检验的基本原理详解
  • 二、预训练模型预测(Datawhale组队学习)
  • VScode快速配置C/C++环境
  • 《论文阅读》开放域对话生成——融合个性和知识并基于检索增强的回复生成
  • springboot整合flowable
  • 计算机系统结构
  • 企业级Jenkins实践
  • Python爬虫教你爬取csdn作者排行榜
  • OpenHarmony如何切换横竖屏?
  • 234. 回文链表