在当前任何具备社交场景的app应用中,用户之间会由于不少行为产生关系,例如微信好友的关系,当前各类陌生人社交软件喜欢的关系,微博粉丝与博 主的关系,当前各类直播软件中粉丝与主播的关系。当前产生关系以后,一个用户全部关注的用户产生的内容就造成Feed流,这个时候须要设计一个合理的Feed流系统。mysql
如今大多数关系产生Feed流系统能够分为两种实践场景,一种是朋友圈类型,我在这里叫作wx类型,一种是微博关注博主类型,我在这里叫作wb类型。redis
wx类型场景,一个用户被关注的其余用户的数量上限不会太大,例如微信一个用户的好友多一点可能就几千人,这里能够设计为写扩散模式。sql
wb类型场景,一个用户被关注的其余用户的数量多是一个很大的值,例如微博一个大V博主的粉丝可能达到几十万、几百万、几千万这种,这里须要设计为读扩散模式。数据库
什么是写扩散模式,什么是读扩散模式?顾名思义,写扩撒,就是将一个内容写多份,例如一个用户发一条朋友圈内容,除了写入本身的朋友圈列表外,须要将这条朋友圈内容写入全部关注他的其余用户的朋友圈内容列表,这样就是一条朋友圈内容就的发布就要写入多个列表,这个就叫作写扩散;读扩撒,就是一个内容被多读,例如一个拥有千万粉丝的微博大V发布了一条微博,不可能将这条内容逐一写入到全部粉丝关注内容列表里,这样的一个内容写入时间会很长,这样会致使一次瞬间写入量会很大,若是一个时间段有不少大V同时发布微博,写扩散的模式对系统的性能会有很大的损耗,这样就只能先只写一分内容,等到用户下次来刷新查看的时候再来直接获取这个大V用户发布的内容,这样就是读扩散的模式。缓存
可是,读扩撒的设计也会有一个问题,那就是若是一个用户关注了几万,几十万个大V博 主怎么办呢?难到是一次将全部关注的大V博发布的内容所有拿出来?显然这样确定是不合理的,下面两种模式下的Feed流系统设计中会有解答。微信
feed_info表结构设计架构
字段 | 类型 | 说明 |
---|---|---|
id | bigint | 主键id, incr id |
uid | bigint | feed内容所属用户id |
create_uid | bigint | feed内容建立用户id |
feed_id | bigint | feed内容id |
type | int | feed内容类型 |
content | varbinanry(4096) | feed内容信息 |
status | tinyint | feed内容状态, 默认status=1, status=1正常, status=2删除 |
score_id | bigint | feed内容排序id |
create_time | datetime | feed内容建立时间 |
update_time | datetime | feed内容更新时间 |
索引设计app
uid、score_id普通索引 create_uid、feed_id惟一索引
分库分表策略数据库设计
根据uid来分表
feed的内容使用pb压缩字符串, 定义feed类型字段用于标记不一样类型的feed, 方便拓展
feed_id生成规则根据建立者用户id生成, 非全局惟一,可是对于每个建立feed用户惟一 score_id按照建立时间按照时间序生成,为16位的int,用于作feed的排序
Feed list缓存设计性能
使用zset结构 key=uid val=create_uid:feed_id score=score_id list 列表只维护固定长度,淘汰老数据
Feed info缓存设计
使用hash结构 key=uid field=create_uid:feed_id val={"content": content, "type": type, "create_time": create_time, ...}
wb类型采用读扩散模式,用户关注的博主或主播在关注Feed列表内当用户刷新时只是展现用户最新的一条Feed内容,不展现全量Feed内容。此外会将已经展现给用户的Feed内写入用户历史Feed列表中,这就是读扩散的模式。
feed_info表结构设计与写扩散模式一致
feed list缓存与feed info缓存与写扩散模式一致
读取关注用户列表offset缓存
使用kv结构 key=uid val=offset
用户最新的Feed缓存
使用kv结构 key=uid val={"content": content, "type": type, "create_time": create_time, "score_id": score_id, "feed_id": feed_id, ...}
feed的状态更新,例如删除操做,经过消费kafka队列来进行同步数据,更新缓存与数据库。
关于每条Feed的评论、点赞、转发不在本文所讨论范围,这些只是feed的某一属性,不属于feed内容自己。
这个是两种模式下关注Feed的设计,有更好的设计欢迎提出建议,做者必定会积极采纳。