年糕妈妈社区做为承接年糕妈妈微信用户到APP的平台,为超百万用户 提供科学育儿服务。社区主要包含关注、推荐、发现、搜索、育儿知识。用户可在社区发帖、参与话题、打卡、评论、点赞、收藏、加关注。mysql
整体架构图以下:
复制代码
3.2.1 拉模式redis
a. 发布帖子简单,A发布帖子,只须要存储到帖子表便可sql
b. 关注取消流程简单,A取消关注B:此时只须要在A的关注列表里删除B,并在B的粉丝列表里删除A。数据库
c. A获取feed流复杂,首先获取A的全部关注用户,而后获取这些用户所发布的帖子并进行排序,分页取出对应的一页帖子。api
优势:缓存
一、存储结构简单,存储量较小,feed数据只存一份
二、关注、发布feed流程简单,容易理解,适合快速开发。
复制代码
缺点:微信
一、获取用户feed流过程复杂,需屡次查询
二、不适合关注人较多的状况下的高并发查询
复制代码
3.2.2 推模式mybatis
当一个用户触发行为(好比发帖子),自身行为记录到行为表中,同时也对应到这个用户的粉丝表,为每一个粉丝插入一条feed。粉丝读取feed流,只须要读取feed流,排序便可。架构
优势并发
拉取feed流 业务流程简单,查询性能高
复制代码
缺点:
一、feed数据存储多份,尤为大V粉丝比较多的状况下,严重消耗存储资源
二、关注取消、发布feed 业务流程变复杂
三、feed可能延迟
复制代码
3.2.3 推拉模式结合
粉丝不少的用户称为大V。普通用户发布feed时,采用推模式。离线用户上线后定时拉取feed,后台将大V的feed同步到该用户的feed流中,来完成动态的拉和推。此模式避免了大V用户发布feed时,fee流存储急速扩大,致使用户查询feed 延迟。
社区展现各类数,好比帖子详情页有阅读数、评论数、点赞数,用户的粉丝数、关注数、消息数等。在计数种类多,并发高下,如何实现数据计数,常见有如下方案。
3.3.1 传统count计数法
好比统计用户发帖数 select count(*) from post where user_id = xxx 来统计,次方法就是 count 计数法。
count计数法实现简单,统计也比较精准,适合数量量小、低并发的业务。
一个计数一个count,实现业务每每须要屡次查询
3.3.2 计数(外置)冗余法
经过对社区计数业务分析,得出2个维度的计数
这2个维度的指标能够经过在用户表、帖子表中添加属性来单独存储,也能够新建2张表 用户计数、帖子计数表存储。
这种方式就是计数外置法,也是一种数据冗余方法。
优势
一、一次查询多种计数,一个维度计数无需屡次查询
二、查询走主键索引,效率高
复制代码
缺点:
一、数据冗余,可能出现数据不一致状况
二、在高并发下,db 压力增大
复制代码
3.3.3 计数外置改进方案
针对年糕妈妈社区业务,咱们抽象出计数服务中心(气泡服务),经过redis缓存实时计数,定时将redis计数数据同步到db。 这样避免了高并发给db带来的压力,同时提升了计数读写能力。
业务背景:社区搜索,经过输入关键词、选择 标签,查询帖子、育儿知识等。
3.4.1 搜索选型:
mysql5.6.4 及以上的innoDB 也引入了全文检索,可直接经过match 查询,方案简单,但内置的分词、搜索效果不必定能知足要求。 仍是选择了更专业的搜索引擎elasticsearch 、opensearch
3.4.2 索引同步实现
全量同步
历史数据同步,经过扫描全表,将数据同步到索引里
复制代码
增量同步
新增数据、或修改数据同步。
方案一:在业务代码中,将数据同步到索引
优势:实现简单,数据同步分散在业务中,有业务维护
缺点:耦合高,业务代码混乱,没法复用
方案二:经过监听数据库的 binlog 日志,将数据同步到索引
优势:解耦,可复用
缺点:引入了额外的框架,增长了系统的复杂度
最后咱们采用第二种方案,经过引入canal,实现binlog订阅和数据同步
复制代码
3.4.3 索引查询
使用搜索引擎自带API
须要学习成本,每位开发都须要额外学习api使用。有没有一种你们不须要学习就会用的工具呢
自研 esqlParse
结合 mybatis,将sql语句翻译成搜索引擎的API,实现索引查询。
优势:下降了开发学习成本,开发只须要写sqlmapper,便可实现索引查询
缺点:功能还不完善,某些复杂查询还不支持
架构都是创建在业务之上,很难一次作的最好,更多的是一步步演进而来的。本文还有不少不完善的地方,也有过其余问题没讲解到,欢迎你们多多交流!
nicomama:清风笑