https://www.zhihu.com/question/19645686/answer/85075806
一、调研 - 懂车帝
1 展示
1)没有关注 or 没有登陆
- 顶部 - 推荐关注作者
- 接口:加载5个未关注的推荐作者
- 给出更多作者入口
- 下部 - 推荐信息流
- 接口:推荐信息流,都是视频
- 以 behot_time 为序,非 display_time
2)关注后
- 顶部 - 已关注作者
- 头像星标:如作者有新文章,头像星标提示
- 接口:给出关注作者列表,带有作者最新发布 display_time 时间
- 点击头像:小图滑动展示作者展示时间最新5篇动态,并提供更多动态入口
- 接口:请求作者时间排序文章5篇
- 点击头像后,星标消失
- 关注更多:展示推荐关注入口
- 头像星标:如作者有新文章,头像星标提示
- 下部 - 关注的信息流
- 展示关注作者的动态,类型不拘
- 以 behot_time 为序,非 display_time
2 动作
未分库分表,in 可以走索引
1)上拉
- 带上 min_behot_time 参数,为上次加载数据的最大 behot_time,第一次请求不传
- 刷新 behot_time 大于 min_behot_time 的数据
- 本地已加载数据清空
2)下拉
请求新数据
- 带上 max_behot_time 参数,为上次加载数据的最小 behot_time
- 请求 behot_time 小于 max_behot_time 的数据
- 拼接在本地已加载数据后
3 讨论
1)behot_time 与 display_time
- 信息流里都是按 behot_time 排序,按display_time 展示的
- 一篇动态的 behot_time 是可更新的,出现过更改的情况
- behot_time 更新规则未知
- 据名称“变热时间”推测,有可能是一定时间区间内请求数到阈值后更新
2)展示内容 - 作者与类别
目前看到的请求,每次8个动态,未发现根据作者或动态类别平均展示的情况,都是按 behot_time 顺序,可能连续都是同一作者的动态,也可能连续都是同一类型的动态。
二、设计 - 拉
基于“按照发布时间顺序展示关注对象的动态(视频、文章、微头条)”,未分库时的设计:
假设每次请求返回数据 N 条:
- 若动态展示无需分类,则每类请求 N 条,再合并排序,返回前 N 条。
- 若动态按分类有数量限制,则每类请求各自的 n1,n2,n3…条,合并排序返回前 N 条。
- 若合并排序前总数不及 N,还需再次尝试请求某项类别,补足 N 条后排序
请求时后台判断关注数:
- 如有关注,则查询条件中有media_id
- 否则,查询所有作者或推荐作者的数据
1 上拉
1)首次请求
请求处理
- 在各个来源(视频、文章、微头条)里,取关注对象的最新N条记录
where media_id in (...) order by create_time limit 0,N
- 合并结果内存中排序,返回前N条数据。
查询次数:m(来源数)
涉及数据:m*N(展示数)
结果处理
- 若存在返回数据,则展示新数据
- 若不存在,则提示无动态
2)再次请求
请求处理
- 请求参数带有 min_time,值为上次请求的最大 create_time
- 在各个来源(视频、文章、微头条)里,取关注对象的在最小时间时间之前的N条
where media_id in (...) and create_time > $min_time order by create_time limit N
- 合并结果内存中排序,返回前N条数据。
查询次数: m(来源数)
涉及数据:m*N(展示数)
结果处理
- 若存在返回数据,则清空本地已加载数据,展示新数据
- 若不存在,则保留本地已加载数据,提示无更新
2 下拉
切换到关注页时,若本地没有已加载数据,都会自动“拉取”一次,所以请求处理都有max_time。
请求处理
- 请求参数带有 max_time,值为上次请求的最小 create_time
- 在各个来源(视频、文章、微头条)里,取关注对象的在最大时间时间之后的N条
where media_id in (...) and create_time < $max_time order by create_time limit N
- 合并结果内存中排序,返回前N条数据。
查询次数:m(来源数)
涉及数据:m*N(展示数)
结果处理
- 若存在返回数据,拼接在本地已加载数据后面
- 若不存在,提示无更多内容
三、设计 - 推
效率太低
1 timeline 表
属性 | 含义 |
---|---|
id | 主键 |
user_id | 用户id |
media_id | 媒体id |
source | 来源(1视频;2文章;3微头条) |
source_id | 来源id |
post_time | 发布时间 |
唯一索引(user_id+media_id)
普通索引(user_id+post_time)
2 操作
1)用户查询动态
- 在 timeline 表查询用户小于 max_time 的前 N 条新动态
select * from timeline where user_id = $user_id and post_time < $max_time order by post_time limit N
- 根据 source 和 source_id 去各渠道获取动态详情,合并排序返回
select * from source_table where source_id in (...)
查询次数:1 + m(来源数)
涉及数据:N+N(展示数)
2)用户关注新媒体
- 查找新关注的媒体的各个来源所有动态
- 各来源动态内存合并,批量插入到 timeline 表
insert into timeline (...) values (...), ... (...);
查询次数:m(来源数) + 1
涉及数据:K+K(媒体所有动态数)
问题1
考虑媒体动态的增删操作与 timeline 表的事务问题
问题2
若媒体动态过多,一次批量插入长度超限或时间过长。考虑分批次批量插入。
3)用户取关媒体
删除 timeline 表中该用户和相应 meidia_id 的数据
delete from timeline where user_id = $user_id and media_id = $media_id;
查询次数:1
涉及数据:K(媒体所有动态数)
4)媒体发布新动态
- 查找关注媒体的所有用户
- 对每个用户生成数据,批量插入动态到 timeline 表,就 user_id 不同
insert into timeline (user_id,...) values ($userId1,..), ... ($userIdn,...);
查询次数:1+1
涉及数据:L+L(关注媒体的用户数)
5)媒体删除动态
- 查找关注媒体的所有用户
- 根据source和source_id删除
delete from timeline where source = $source and source_id = $source_id
查询次数:1+1
涉及数据:L+L(关注媒体的用户数)