抖音顶部的关注栏没有了怎么办(抖音的工具栏打开的方式)

抖音作为国民短视频社交应用,有数据显示总用户数量已超过8亿,每日活跃用户达7亿,人均单日使用时长超过2小时。在这样庞大的用户基数下,一个小小的功能,背后可能需要复杂的设计。以用户服务为例,单单存储8亿用户,已经远远超出单库单表MySQL的极限。本文中我们的问题是如何在这样的用户基数上,实现关注列表、粉丝列表功能。

需求分析

事实上,关注列表、粉丝列表只是需求的一部分。抖音上人与人的关系是一种弱关系,可以单方向进行关注,这一点与微博、twitter类似。作为对比,微信上人与人的关系是强关系,必须是对等的。

如果打开抖音,我们可以看到三个标签:朋友、关注、粉丝。

抖音顶部的关注栏没有了怎么办(抖音的工具栏打开的方式)

 

这三个标签分别对应:

  1. 查询自己的朋友列表,并支持搜索(互相关注)
  2. 查询自己的关注列表,并支持搜索(关注的用户)
  3. 查询自己的粉丝列表,并支持搜索(关注你的用户)

除了这三类读操作之外,还有一些写操作:

  1. 关注
  2. 取消关注
  3. 拉黑
  4. 取消拉黑等等

数据分布

凭经验来看,每个用户关注的用户数是有限的,大概率不会超过5000; 一个普通用户的粉丝数也是有限的,能超过5000至少说明精心运营过。

但超级大v的粉丝数可以远远超出这个量级,比如在抖音上搜索“刘德华”、“邓紫棋”、“王一博“等,粉丝数都是千万级别的。精心运营过的刘德华粉丝数达到了惊人的7600w,这个量级可以给他定制化一张MySQL表了,表名就叫liudehua_followers

抖音顶部的关注栏没有了怎么办(抖音的工具栏打开的方式)

 

当然,定制化一张MySQL表只是一个玩笑。但一个事实是,刘德华的粉丝数是我的100w倍;我们没有渠道得知抖音用户的粉丝数分布,马太效应肯定是超级明显。

存储架构

关注关系本质上是一种关系,但业务上体现为两种:粉丝列表和关注列表。朋友是粉丝列表和关注列表的交集。如果设计一种存储架构,需要满足一些条件:

  1. 持久化存储: 关注关系存起来以后,不能丢
  2. 数据一致性: 粉丝列表和关注列表的数据必须一致
  3. 高性能: 查询和更新都必须快,比如内网服务接口响应100ms以内
  4. 架构简单、资源占用可接受

先不考虑数据量,如果用一张MySQL表存储关注列表,那么结构大概是这样的:

1. uid bigint
2. follower_uid bigint
3. status tinyint
4. create_time tiimestamp
5. modify_time tiimestamp

在 uid 和 follower_uid 都加上索引,用Go写个服务封装成接口,就可以用了。

但是,这是8亿用户,分库分表肯定是少不了的。一旦做了分库分表,关注列表和粉丝列表都必须分开存储了,因为:

  1. 如果用uid做分片,通过 follower_uid 取关注列表时,数据分散在不同的分片上,读写的效率都会很低,还不支持分页
  2. 如果用 follower_uid 做分片,通过 uid 读取粉丝列表时,会遇到同样的问题

所以,粉丝列表仍然使用上面的表结构,uid是用户ID,follower_uid是粉丝ID,对uid进行分片;

关注列表则采用稍微不同的表结构,uid是用户ID,following_uid是被关注用户的ID,对uid进行分片:

1. uid bigint
2. following_uid bigint
3. status tinyint
4. create_time tiimestamp
5. modify_time tiimestamp

按照功能拆表、对表进行分片,这两个操作完事以后,我们满足了持久化和高性能两个指标,但如何保证两张表数据的一致性呢?

我们简单聊一下CAP理论:

  • Consistency 一致性
  • Availablity 可用性
  • Partition Toloerance 分区容错性

在一个大型分布式系统中,这三点不可能同时完成。我们看CAP理论如何应用到粉丝场景。

在粉丝场景中,我们需要纠结的是C和A选哪个。

如果选C,那么就需要依赖分布式锁,保证两张表都写入以后,才返回结果给客户端;这里的缺点很明显: 一是引入外部依赖(分布式锁),锁挂了怎么兜底;而且性能差;

如果选A,就是最终一致性方案。当关注行为被触发时,优先将数据写入“关注表”(没有马太效应、性能可控),通过消费Binlog更新数据到“粉丝表”;

权衡到业务场景的要求、技术实现的成本、服务的稳定性,选A更优。

业务支持

场景1: 朋友列表

  1. 通过uid获取“关注列表”,list<following_uid>
  2. 通过folloing_uid + uid,反查“粉丝列表”

场景2: 通过名字搜索

  1. 先找到粉丝或关注的 uid list
  2. 用 list + 名字搜索user表(或存放用户信息的ElasticSearch)

这两个场景下,如果是普通用户,基本上没啥问题。

如果我是刘德华,场景1倒是没啥问题,场景2如果搜索的是粉丝,那么性能上也会有问题,怎么解决呢?解决办法就是不让大V搜索。

胖客户端的一点联想

客户端和服务端的分界线从来都不是那么清晰,随着历史的演进,

大学那会儿,教科书上会说浏览器是瘦客户端,桌面应用是胖客户端。

上面提到的存储设计,或者上层的接口设计,都是服务端做的事情。抖音需要服务这么大的用户群体,本身已经需要很多机器。每个看起来微不足道的请求,QPS一旦上来,需要的机器数量都不会少。那么有没有一种方法,可以减少机器占用呢?

当然有,由于目前手机的配置普遍都比较高,很多原本在服务端的信息,都可以缓存到手机内置存储里。只需要一定的更新机制,保证服务端和客户端的数据一致即可。不然手机端的app怎么都这么大呢?

抖音顶部的关注栏没有了怎么办(抖音的工具栏打开的方式)

 

因此,粉丝列表、关注列表这类数据对都可以缓存到App端。粉丝列表的变更从服务端定期拉取更新;关注列表的变更由App端触发,只需要保证服务端接口调用成功后,更新本地缓存即可。

用本地缓存的数据支持复杂的查询,大大压缩了数据量,解决大表JOIN的问题,模糊搜索玩出花也可以!

版权声明:本文内容由网友提供,该文观点仅代表作者本人。本站(http://www.zengtui.com/)仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 3933150@qq.com 举报,一经查实,本站将立刻删除。

版权声明:本文内容由作者小航提供,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至907991599@qq.com 举报,一经查实,本站将立刻删除。如若转载,请注明出处:http://www.hangzai.com/343250.html

(0)
小航的头像小航

相关推荐