10 亿用户数据分库分表设计

2020-02-28 23:34:48 +08:00
 pabno

使用 mysql 存储 10 亿的用户数据,用户表的设计是 (bigint user_id, bigint phone, varchar email)

查询分为两类 case:

  1. 用户登陆,可能会使用 phone 登陆,也可能使用 email 登陆
  2. 登陆后操作用户数据

目前方案:使用 user_id >> 32 % 2 分库,user_id >> 22 % 20 分表。user_id 由雪花算法生成

针对 case 2,直接用 user_id 取模就很容易定位到具体到库和表,但是 case 2 需要使用 email 或者 phone 反查 user_id. 暂时想到的就是在对 email,phone 分别进行分库分表再做查询,然后将数据缓存到 redis 中。当用户使用 phone 或者 email 进行登陆时,先查询缓存中有没有数据,没有再计算相应当分片库和分片表进行查询

不知道还有没有什么比较好的方案

7654 次点击
所在节点    程序员
37 条回复
dragonsunmoon
2020-02-29 13:24:43 +08:00
不过设备也很牛逼呀, 假设单个设备的成本是 10.00 元, 光设备他妈的也要 100 亿元. 还不算分发,部署,运维,网络通讯费,后台带宽服务费, 后台服务器,存储等费用. 这个系统真弄下来, 耗费巨大呀
brucefu
2020-02-29 14:27:13 +08:00
这些数据分表就可以了啊,为嘛要分库
brucefu
2020-02-29 14:30:38 +08:00
@dragonsunmoon 注册的多,活跃的少
mreasonyang
2020-02-29 18:18:46 +08:00
@dragonsunmoon 这个很常见啊,又不是自然人
GDC
2020-02-29 18:50:57 +08:00
@akira 用户 10 亿的大厂不需要来 V2 问这样的问题…
mysunshinedreams
2020-02-29 19:57:29 +08:00
@dragonsunmoon 其实你理解的太绝对了,举个例子,一台手机,可能对应几十个设备 ID,因为用户存在各种各样的复原的操作,举个实际的例子,亚马逊对 Kindle 设备的管理,如果你经常重做系统的话,就会发现它们的识别策略是每一次都会识别为一个新的设备。
dragonsunmoon
2020-02-29 22:58:27 +08:00
@pabno 不好意思,我的回复是稍微带着点调侃的味道,先对你说声 sorry
虽然是带着点调侃的话,可是我想说一下技术外的问题. 先从"10 亿用户"这个数量来说. 题主在问题里给出的表设计描述: 用户表的设计是 (bigint user_id, bigint phone, varchar email). 用户是以手机和电子邮箱为用户标识的.
@mysunshinedreams 但从表的字段来说,注册的对象背后是手机号码和邮箱这种身份标识资源, 与具体设备无关.不存在一个手机对应几十个设备 ID, 因为关注的是 phone 和 email
因为现在是移动互联网,所以普通用户使用邮箱注册的毕竟是少数,我们先假设 10%的用户是使用邮箱注册,另外 90%使用手机注册. 抛开 1 亿个邮箱注册的用户, 剩下 9 亿个手机号码. 再假设人均 2 个号码(实际生活里, 绝大多数"正常用户"只会使用一个手机号码, 并且,人均 2 个号码这个数值其实已经给得很高了,这里是为了方便计算, 如果调低了,只会让计算出来的真实注册用户数更多).

回到之前的描述, 假设人均 2 个号码都注册了, 那么使用手机号码注册的人数也有 4.5 亿. (还没有把使用 email 来注册的用户算进来). 4.5 亿个用户, 大家能理解这是个什么概念吗?
如果题主所在的公司是一个小公司或者初创公司. 我认为 10 亿用户 数,根本就是个伪命题. 因为, 很大程度上, 等系统上线后, 能不能撑到 100 万的注册用户数, 都是个未知数. 所以担心一个几乎根本不可能发生的问题, 没有必要.
如果题主所在的公司, 依旧有一定的规模. 有超过 100 万的注册用户, 我觉得这个公司也应该有钱请个资深的架构师来解决这个问题(重构系统), 就像 @GDC 所说的,应该也不会来 V2 问这样的问题了.
这让我想起来多少年前业界的一个笑谈. 一帮人创业, 先用 ruby on rails 开发出产品原型, 上线. 然后融到资, 接着再招聘另外一帮 java 的人, 把 ruby 写的系统再重构到 java 上. (Twitter 还真就是这样的)

@pabno 我觉得, 你现在所处的公司应该是个初创企业(我猜的, 如果我猜错了话,这些回复内容就当做废话随便看看吧) 你其实你现在根本就不需要担心 10 亿用户这个问题. 因为到 10 亿用户, 整个系统面临的不仅仅是用户登录查询的问题. 10 亿用户, 假设 10%的的活跃用户, 那就是 1 亿的活跃用户. 这些用户在你们系统里的行为活动, 会产出大量的数据. 这已经不单单是一个用户表设计的问题了.
量变引起质变, 海量用户数据的处理,会引申出一系列的问题, 单机数据库在性能(tps/qps), 容量上不够. 需要分布式数据库, 按照业务领域进行垂直分隔, 按照数据进行水平拆分. 分库,分表,数据归档. 引入 no sql 的数据库在应用层建立索引服务, 媒体数据的海量存储, 加速访问的 cdn. Api 应用服务的负载均衡, 微服务,集群,数据容灾备份等等. 更别说, 处理海量数据所需要的云计算的云主机,带宽,存储等资源, 需要的也是流水般的费用呀.

但是, 对于一个初创公司的初创项目, 压根就不需要考虑海量数据问题. 因为初期压根就不会遇到海量数据带来的问题.
不要提前过渡设计. 一开始也不要把问题给复杂化. 不要试图做一个完美的系统. 不要考虑你几乎不会遇到的问题.
dragonsunmoon
2020-02-29 23:38:18 +08:00
@pabno 我才留意到你在后面的回复里, 指出是以用户表设计来当做类比场景的.
但是, 即便以设备数来说, 10 亿个设备数也是很大的数字. 考虑到 @mysunshinedreams 所说的, 对应几十个设备 ID 的情况, 会有,但是不会是普遍情况, 对应几十个设备 ID 的情况占比应该很小的. 所以我们粗略的给定一个设备的 ID 重复产生系数, 假设为 2, 那么也有 5 亿的设备. 这个设备数量已经很高了. 5 亿设备中, 假设有 1 亿个活跃设备, 每天产生 10 条数据. 每条数据假设为 1KB (因为不清楚业务类型,不清楚实际情况,这个值可能高, 也可能低了, 暂时先用这个值来描述问题), 一年产生的纯数据容量(数据进入到数据库后, 还会有索引等, 所以实际需要的存储容量只会比这更高) 约为: 100,000,000 * 10 条 * 1 KB / 1024 / 1024 / 1024 * 365 天 = 339.93 TB

所以, 真有 5 亿个设备, 是会产生海量数据问题的. 而海量数据问题的性质, 复杂度, 解决方法, 已经超过表设计这个问题范畴了.

初期,不要考虑海量数据问题. 因为, 很大概率上, 公司都不能撑到有那么多的用户量 /设备量.
如果真的遇到了海量数据问题, 那么恭喜你们! 你们项目,你们的事业已经成功一大半了.
pabno
2020-03-01 03:19:29 +08:00
@justRua 有考虑过这个方案,不过太贵了
pabno
2020-03-01 03:23:37 +08:00
@cabing 原来也想着映射关系方 redis 做持久化的,但是一个设备可能一两个礼拜才会做一次登陆
pabno
2020-03-01 03:36:23 +08:00
@dragonsunmoon 我们海外和国内都有业务,设备数还是比较大的。其实现在这些数据都有落地在我们的大数据平台,现在是想整合这些 id 做营销,最主要是生成一个统一的 ID。据反馈 19 年 Q4 以来的设备数就已经有 2 亿了,这还是 18 年底被谷歌点名后设备数大幅度下降后的

老板的事业是挺成功的,我只能争取努力努力,帮老板再买一辆玛莎拉蒂
dusu
2020-03-01 03:48:57 +08:00
光从性能角度来说

一级热数据进 redis (取最近登录多少天)

二级进 pika 或 ssdb 这类 kvdb (取最常登录多少次)

三级命中走 mysql 分表查询

无论存还是查 100 亿都问题不大
staticor
2020-03-01 08:20:36 +08:00
少了描述背景, 会带来更多的问题

有种 X/Y problem 的味道
cabing
2020-03-01 11:53:10 +08:00
@pabno

如果觉得 redis 成本高。

持久化方案不一定非得放内存。

ssd+lru(内存)


ssd 1T 也不贵。内存不用太大,lru 就行。
sagaxu
2020-03-01 11:54:09 +08:00
去年就有两亿设备,业务遍布全球,这样的公司没有架构师也没有 dba ?难道是触宝么
mysunshinedreams
2020-03-01 12:35:11 +08:00
@dragonsunmoon 你忽略了黄牛,黄牛的设备并不一定是真实设备,但是他们能弄出庞大的设备群体,举个例子,X 团,一些低价促销活动,会有很多黄牛再抢,他们用的就不是真实的设备。
watsy0007
2020-03-01 15:36:45 +08:00
分区就可以了吧. 查询压力有多大

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/648471

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX