订单列表上,用户可以看到他下的单一页的,好多,那么表数据很多,有好多亿条,那么怎么设计?
答:水平分表,使用用户 id 做 hash
那么已知订单 id,怎么获取订单详情?
答:union 订单表
上万的表直接联合么?
思考。。。答:可以维护 uid->订单 id 的 k-v 结构在 redis 中
扩展下,已知 XX (忘了啥字段了,当时紧张了)获取订单详情呢?
答:那就存个 hash 对应关系
司机的 APP 也能显示订单,怎么获取呢?
思考。。。答:不会了,之前公司都是千万级数据,没做过水平拆分
面试官怒了,你可以滚了,回去等消息吧
好的,我滚了。。。。(确实没做过啊,能想的我都想了)
当时太紧张了,前面的算法没答上来,有点自暴自弃,现在想想有了点答案了,只是我不知道对不对,请教大神这题答案
1
oppoic 2020-12-16 22:24:49 +08:00 via iPhone
那是面试官原话吗?
|
2
nightspirit OP @oppoic 滚那个不是,我内心虚拟的,但能感觉面试官的鄙夷,前面算法还有锁的问题 我都答错了
|
3
wellsc 2020-12-16 22:32:11 +08:00 via iPhone
橙心优选还是出行啊
|
4
uiosun 2020-12-16 22:43:24 +08:00
坐等答案,这个数据体量,这种问题,该解决啊……
|
5
jandou 2020-12-16 22:50:02 +08:00 via iPhone
以前问过同样问题,他们家常规题目。
|
6
beidounanxizi 2020-12-16 22:53:54 +08:00
nosql hbase 可以做查询 另外 滴滴面试官 嗯 不说了
水平分表的话 排序 join 都不好操作 感觉楼主也是个憨批 有啥好怕的 🐶 |
7
opengps 2020-12-16 22:55:47 +08:00 2
很多时候考察的不是是不是会做,而是会不会去思考这种问题。
我以前 gps 项目面试也这么问过,然而能有思路的人太少,当然不像滴滴这么有实力可以挑面试的人 订单表作为需要联合查询,可能我分享的单表逻辑不适用,不过可以发出来分享下,外加其他比如一主多从等方案的结合应该可以适当提高下得分 https://www.opengps.cn/Blog/View.aspx?id=284&from=v2ex |
8
fantastM 2020-12-16 22:57:51 +08:00
订单 id -> 用户 id,用户 id -> 订单 id
|
9
fantastM 2020-12-16 22:59:16 +08:00
#8 这两个关系都存一下
|
10
Vegetable 2020-12-16 23:03:29 +08:00 1
这提问方式压迫感挺强的,后续问题都是基于你的答案提的,挺考验临场水平的。
我感觉你后边的问题没答出来不是因为没有答案,而是他前边给的需求太少,按照这种条件给出来的答案本来就是设计不足的。 单纯的寻求这个答案好像不是很重要吧,超纲了等答案 |
11
CEBBCAT 2020-12-16 23:46:10 +08:00 via Android 2
楼主的第一段我实在读不通畅
|
12
nightspirit OP @CEBBCAT 语文功底不是很好,他的意思是用户可以看到他所有下的订单,我们好多用户,订单表很大,我们怎么处理订单表
|
13
nightspirit OP @beidounanxizi 因为面试机会少,有点患得患失
|
14
rocky114 2020-12-17 08:47:42 +08:00
司机的 APP 也能显示订单,怎么获取呢?
司机应该常看的订单就是六个月吧?六个月内的数据维护一份 map,六个月之前的数据查询慢就慢一点吧 |
15
nightspirit OP @wellsc 做外卖的,不知道是哪边,我不熟
|
16
angryfish 2020-12-17 09:12:03 +08:00 via iPhone
对这类问题表示关注,等大神来回答
|
17
cxshun 2020-12-17 09:17:28 +08:00 1
@nightspirit #15 一般情况下,你要分表就需要按多维度去分,比如订单表,有可能按用户查,也有可能按订单查,那 OK,我们就按 [用户 ID] 和按 [订单 ID] 两个维度去分表,冗余多一个表。查询的时候根据不同条件查不同的表,也就是分不同的 DAO 或 Mapper,我们之前就是这样做的。
当然,其实还可以上 ES 的,当量大到一定程度,比如上亿,mysql 有可能撑不住,那上到 ES 是自然而然的事情了 |
18
simapple 2020-12-17 09:19:34 +08:00
原则上规避 io 瓶颈,先用设计策略,快速查询到必要的查询条件,再通过一个可控制数据返回量的条件查询,查出单个 request 需要的数据。如果必要,再设计预查询策略,在资源可用的情况下,提前准备好下一个 request 的数据。
|
19
nightspirit OP @cxshun 多谢 思路多了起来
|
20
zardly666 2020-12-17 09:37:32 +08:00
能想到的就是每个用户都冗余维护一个订单列表的缓存项。在下单逻辑的时候,实时把缓存更新,查的时候就是秒查了。。坐等大神解答
|
21
wellsc 2020-12-17 09:38:09 +08:00 via iPhone
@nightspirit 滴滴外卖不是几年前就无了,难道是滴滴海外?
|
22
DebugTy 2020-12-17 10:04:08 +08:00
如果真的是详情数据落在了很多表里面需要聚合, 这个可以考虑用宽表 tidb 把所有信息聚合到宽表中, 如果订单需要筛选可以先查询 es 只筛选出订单号, 再去查 tidb 补充详细信息;
|
23
nightspirit OP @wellsc 海外
|
24
rming 2020-12-17 10:17:17 +08:00 3
基因法,让大部分查询条件都带上用户 ID 的基因,冗余关联表也是个办法,还是回答不够系统和完整,可能面试官期望回答是一套系统的总结分析和实践经验
|
25
murmur 2020-12-17 10:23:03 +08:00
|
26
lasuar 2020-12-17 10:35:06 +08:00 1
还是没太看懂描述,说说我的理解:
1. 用户要在一页内显示完所有的订单(不分页?) 答:个人觉得可以在(user_order_ref)表内存储 uid 和 order_id_list 的关联关系,order_id_list 字段是 json 数组,mysql/mongodb 都可以容易的做 json 对象的操作,那么这张表的数据量就<=user 表,不会太大,也就不需要分表,那么这里就可以拿到用户所有的订单 id 。 (有的人也许会考虑部分 rows 的 order_id_list 字段过长带来的一些对表空间的影响,其实我认为可以忽略,因为一个用户的订单量上天了也不过几千几万,这点量不会有什么影响) 然后就像楼主说的,订单详情表使用订单 id 做 hash 水平分表,这里就能查到一个用户所有的订单详情了。 2. 司机的 APP 也能显示订单 答:司机 APP 显示自己的订单,其实与用户订单没啥不同,按照前面的做法,是可以实现按排序分页的(计算出要读哪些订单表,然后 union+orderby )。 个人愚见。 |
27
yzbythesea 2020-12-17 10:41:34 +08:00
一般大公司面试两个技巧,
1. 存数据用 nosql 2. table 拆得越细越好,别把逻辑分给 database 。 你这个可以是 3 个 table, order table, oder ID -> order user table, user ID -> order ID driver table, driver ID -> user ID |
28
f12998765 2020-12-17 13:54:27 +08:00
第一反应是来个 kylin 吧
|
29
DoctorCat 2020-12-17 15:44:19 +08:00
公有云上丢 DynamoDB 给他看 ,私有化部署用 Cassandra
告诉面试官:您知道么,mysql 不能 allin 所有的业务场景的。 |
30
zhengdai1990 2020-12-17 15:53:19 +08:00
走 ES 啊,哈哈哈哈哈
|
31
lewis89 2020-12-17 17:32:58 +08:00
所有的分库分表实际上 处理问题的方式 都是差不多的,要么冗余数据 要么冗余关系
|
32
zhangyp123 2020-12-17 18:03:05 +08:00
基因分库 + 数据冗余 解决 “多 key” 类业务 参考: https://cloud.tencent.com/developer/article/1689831
|
33
melkor 2020-12-17 18:49:28 +08:00 via iPhone
单据维度数据按 ID hash 拆分存,用户维度的存用户 ID 到单据 ID 的映射,司机维度的也一样。用户也不会一次看所有的单,可以按用户维度预缓存一页的单。如果用户要看后面的单再去查存储。
|
34
nightspirit OP @yzbythesea
我理解一下这三个表,看是你说的这样不 order table, oder ID -> order 订单 i 按照 id 取模分表 user table, user ID -> order ID 用户表 然后 nosql 存储用户 uid->订单 id driver table, driver ID -> user ID 司机表,nosql 存储 司机 id->订单 id |
35
yzbythesea 2020-12-18 11:37:24 +08:00
@nightspirit 是的。甚至 order table 也可以是 nosql,然后 order 的内容纯成 json,读到你 service 里在取各项的值。
想了下觉得 driver ID -> order ID 要好一些。因为同用户肯定乘坐了不同的司机。 |
36
nightspirit OP @lasuar 分页,他意思是订单表太大,怎么查订单列表
你说的这个我不是很理解 uid 和 order_list 的关联关系数据量怎么会小于用户表?用户对订单是一对多的关系,那如果是 order_list 存数组,你说的数组增加影响可以忽略,我没这么做过,不了解,还有就是用户表了,我认为滴滴用户也不少,有可能一人有多个账号,我觉得数据量也不小。 |
37
lasuar 2020-12-18 13:22:46 +08:00
@nightspirit 我写的应该足够清晰,你可以在读一遍; user 表是否再分表也是没关系的。
|