阅读 886

年糕妈妈社区架构实践

1、社区介绍:

年糕妈妈社区作为承接年糕妈妈微信用户到APP的平台,为超百万用户 提供科学育儿服务。社区主要包含关注、推荐、发现、搜索、育儿知识。用户可在社区发帖、参与话题、打卡、评论、点赞、收藏、加关注。

2、社区实现难点

  • feed实现,如何保证高并发低延迟
  • 高并发下各种数据统计。一个页面有帖子阅读数、评论数、点赞数,用户的粉丝数、关注数等
  • 分页查询标签下的文章列表各种排序

3、社区实现方案

总体架构图如下:
复制代码

3.1 feed介绍

  • feed:feed流中的每一条消息都是Feed,朋友圈中的一个消息就是一个Feed,微博中的一条微博就是一个Feed.
  • feed流:持续更新并呈现给用户内容的信息流。每个人的朋友圈,微博关注页等等都是一个Feed流。
  • Timeline:Timeline是一种Feed流的类型,微博,朋友圈都是Timeline类型的Feed流
  • 年糕妈妈社区的关注feed 是由关注的人发布的帖子组成。

3.2 feed流实现模式

3.2.1 拉模式

a. 发布帖子简单,A发布帖子,只需要存储到帖子表即可

b. 关注取消流程简单,A取消关注B:此时只需要在A的关注列表里删除B,并在B的粉丝列表里删除A。

c. A获取feed流复杂,首先获取A的所有关注用户,然后获取这些用户所发布的帖子并进行排序,分页取出对应的一页帖子。

  • 优点:

      1、存储结构简单,存储量较小,feed数据只存一份
    
      2、关注、发布feed流程简单,容易理解,适合快速开发。
    复制代码
  • 缺点:

      1、获取用户feed流过程复杂,需多次查询
      2、不适合关注人较多的情况下的高并发查询
    复制代码

3.2.2 推模式

当一个用户触发行为(比如发帖子),自身行为记录到行为表中,同时也对应到这个用户的粉丝表,为每个粉丝插入一条feed。粉丝读取feed流,只需要读取feed流,排序即可。

  • 优点

    拉取feed流 业务流程简单,查询性能高
    复制代码
  • 缺点:

    1、feed数据存储多份,尤其大V粉丝比较多的情况下,严重消耗存储资源
    2、关注取消、发布feed 业务流程变复杂
    3、feed可能延迟
    复制代码

3.2.3 推拉模式结合

粉丝很多的用户称为大V。普通用户发布feed时,采用推模式。离线用户上线后定时拉取feed,后台将大V的feed同步到该用户的feed流中,来完成动态的拉和推。此模式避免了大V用户发布feed时,fee流存储急速扩大,导致用户查询feed 延迟。

3.3 计数中心实现

社区展示各种数,比如帖子详情页有阅读数、评论数、点赞数,用户的粉丝数、关注数、消息数等。在计数种类多,并发高下,如何实现数据计数,常见有以下方案。

3.3.1 传统count计数法

比如统计用户发帖数 select count(*) from post where user_id = xxx 来统计,次方法就是 count 计数法。

  • 优点

count计数法实现简单,统计也比较精准,适合数量量小、低并发的业务。

  • 缺点:

一个计数一个count,实现业务往往需要多次查询

3.3.2 计数(外置)冗余法

通过对社区计数业务分析,得出2个维度的计数

  • 用户维度:关注数、粉丝数、发帖数、被赞与收藏数
  • 帖子维度:阅读数、点赞数、评论数、收藏数

这2个维度的指标可以通过在用户表、帖子表中添加属性来单独存储,也可以新建2张表 用户计数、帖子计数表存储。

  • 比发布帖子时,insert post,更新帖子数 update set post_num = post_num ++ where user_id = xxx
  • 查询帖子计数时, select pv,like_num,comment_num from post where post_id = xxx

这种方式就是计数外置法,也是一种数据冗余方法。

  • 优点

    1、一次查询多种计数,一个维度计数无需多次查询
    2、查询走主键索引,效率高
    复制代码
  • 缺点:

    1、数据冗余,可能出现数据不一致情况
    2、在高并发下,db 压力增大
    复制代码

3.3.3 计数外置改进方案

针对年糕妈妈社区业务,我们抽象出计数服务中心(气泡服务),通过redis缓存实时计数,定时将redis计数数据同步到db。 这样避免了高并发给db带来的压力,同时提高了计数读写能力。

3.4 社区搜索

业务背景:社区搜索,通过输入关键词、选择 标签,查询帖子、育儿知识等。

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,即可实现索引查询

    缺点:功能还不完善,某些复杂查询还不支持

3.5 感受

架构都是建立在业务之上,很难一次做的最好,更多的是一步步演进而来的。本文还有很多不完善的地方,也有过其他问题没讲解到,欢迎大家多多交流!

nicomama:清风笑

关注下面的标签,发现更多相似文章
评论