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 进行登陆时,先查询缓存中有没有数据,没有再计算相应当分片库和分片表进行查询

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

7633 次点击
所在节点    程序员
37 条回复
daimaosix
2020-02-29 01:28:00 +08:00
直接上 TiDB,都不用做分库分表,100%兼容 MySQL,就像不曾离开 MySQL
akira
2020-02-29 01:40:01 +08:00
10 亿... 是国内的哪家大厂么。。
peyppicp
2020-02-29 01:45:23 +08:00
email,phone 分别存在两个分片库里,分别关联对应的 uid。比较操蛋的就是新用户进来的时候要双一写了。
luxinxin
2020-02-29 01:48:44 +08:00
其他还好,但感觉登陆并不是啥热数据,不需要 redis 缓存
luckylo
2020-02-29 07:22:26 +08:00
@akira 用户数量能过亿行业就那么些。
传统行业的运营商+银行 +某些垄断行业。这些基本上是 Oracle ,就算不是,也基本跟 mysql 没啥关系。然后就是互联网的那几个大厂
mikulch
2020-02-29 07:35:12 +08:00
@peyppicp 你这个操作相当于数据异构啦,那不上 es 加列数据库了
opengps
2020-02-29 07:59:10 +08:00
登录名缓存下来,值为数据库的路由标识
neoblackcap
2020-02-29 10:08:29 +08:00
同 @peyppicp 的解决方法,采取非规约化的方法对数据库进行处理,分别以 phone, email 为主键(cluster key)建表,关联 user_id。
问题还是在于用户注册时就变得需要一次性写三个表。不过这个不算是大问题,哪怕是后面进行分布式事务,这个性能也是可以接受的。
pabno
2020-02-29 10:53:03 +08:00
@luckylo
@akira
这个只是我类比过来当一个场景,为了方便说明问题。实际上是 10 亿设备(国内外都有业务),但是不同设备可能会有各种不同当 id,比如 gaid,androidid,imeiid
pabno
2020-02-29 10:53:37 +08:00
@luxinxin 这个确实是
pabno
2020-02-29 10:55:29 +08:00
@opengps 想过这个问题,但最终还是需要持久化下来。不然很久没有登陆后重新登陆没有命中缓存就找不到路由标识了
ifconfig
2020-02-29 11:14:41 +08:00
请问下,直接用分区不行么,为什么要分表
encro
2020-02-29 11:48:07 +08:00
应该没有更好的方案,如果通过号码查询的频率高,应该采用 kv 内存存储吧。
没有试过 kv 和数据库 hash 索引,10 亿数量级性能会差别多少。
楼主花半天做一个实验给我们看看?

到达这数量级,就是一个尝试验证改良的过程。
lovelife1994
2020-02-29 11:58:46 +08:00
@neoblackcap 如果登录数据不是热点数据,在有一级缓存的前提下,是不是单表做分区,在查询列上建 non-clustered 的覆盖索引就行了,这样能避免分库的带来的路由,双写和分布式事务的问题。感觉需要根据当前数据规模和预估增长的到的规模做下压测做取舍。如果 phone 和 email 都是可变更的,还要考虑分区,分表,分库间数据迁移怎么做。
neoblackcap
2020-02-29 12:25:56 +08:00
@lovelife1994 我提的那边理论上只要开发支持(分布式事务,查询变更),你说的几点都解决了。无论是 phone, email 的可变更,还是查询的性能。我说的主要是 Cassandra 的解决方案。
不过如同你所说,分布式方案肯定是有其他问题,路由,分布式事务。要结合生产环境取舍(压测)。这样的问题的确可以算是真正架构师的活了。
neoblackcap
2020-02-29 12:29:47 +08:00
@ifconfig 分区还是单机,分表就可以多节点了
justRua
2020-02-29 12:44:23 +08:00
es 存一份用于搜索,mysql 里做分表分库,现公司是这么做的,不过用户数据是千万级,没上亿
cabing
2020-02-29 13:00:31 +08:00
如果是单纯的用户表应该不会涉及到跨表事务吧。
一般的设计,登录相对应该是不频繁。case1 经常使用,case2 不那么频繁


说一个简单的方案:

针对 cace2 可以通过分布式的 kv(持久化)系统去存储,做备份就行,数据的变更,可以通过消息队列去更新。

此外还有针对活跃用户,还需要定期比对 case1 中的和 kv 系统中的数据。

kv 系统,可以考虑小米的 Pegasus,也可以找个类似的 kv 系统,也可以自己根据 rocksdb 撸一个。

如果 kv 系统只是存储 uid 的,

10 亿数据,如果只是存储 email=>(uid) phone=>(uid)

256 * 1000000000/1024/1024/1024 = 238G,其实存储数据量不是特别多。


此方案只是通过一次 email 或者 phone 寻址到 uid,后续的流程还是走到 uid 查询了。
dragonsunmoon
2020-02-29 13:21:00 +08:00
全球接近 80 亿的人, 地球上每 8 个人,就有一个人是你们系统的用户,牛逼,呵呵
dragonsunmoon
2020-02-29 13:22:03 +08:00
哦, 才注意到, 是设备,😅

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

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

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

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

© 2021 V2EX