关于分库分表的一点疑惑

2 天前
 irisdev
平时做的项目都比较小,一般都是几台应用服务器+几台数据库服务器,虽然也有数据库拆分,但基本上都是把不同业务的表放在不同库中,比如一个 erp 系统,将财务相关的表放在某台服务器的某个库中,将仓库相关的表放在某台服务器的某个库中,没有拆分到更细的颗粒度,比如物料表,快上亿条数据了,也没有将这一张表拆分成不同表或者到不同库中。

目前即使是这样也给写代码带来了一些麻烦,比如我负责生产模块,但是有时候要查一些物料数据,这时候就不可避免地要跨库查数据,这样我还可以理解。但是如果有一天物料表要拆分成两张表或者到两个库中,那我写 sql 时岂不是要一样的语句写两遍然后 union 一下了?联想到那些大厂,比如淘宝,所有用户的“足迹”,就是浏览记录,至少得有百亿条数据了吧?这种业务是怎么处理的呢...应用服务器我可以理解,可以 cdn ,可以负载均衡,反正运行的是一套代码。但是数据库我就理解不了了,就算是一个简单的查询,“根据用户得到下单记录”,那也得全表查询吧?难不成这张订单表是单表?不现实。如果这张订单表被拆过,那淘宝的程序员在写代码的时候要考虑各个子库各个子表的情况吗?那不得累死。还是说“数据库集群”(只听过没概念...)可以像服务器集群一样屏蔽连接,程序员写代码就好了?不过在我理解中,服务器集群部署的是代码,转发到哪一台都可以,数据库集群里面的数据都是不一样的,那如果要屏蔽细节提供跟单体数据库一样的服务,内部肯定也通过网络通信然后统一提供给用户,这样感觉会不会对效率也有影响?感觉这些大公司的应用速度还是很快的,尤其是拼多多,感觉查订单记录就跟查几万几十万的表一样。

因为这块懂得太少,表达地比较乱,也没法专业地表达,见谅..但意思应该表达出来了,这个疑问困扰我很久了,有没有明白的说两句,感谢
3579 次点击
所在节点    数据库
48 条回复
crysislinux
1 天前
我对这块也有类似的疑问。我自己的感觉是下面的实现很可能还真就是大力出奇迹,我们往往低估数据库的能力,就像我们容易从身边的生活经验去估计工业材料的强度一样。

另外很多大型应用从 UX 设计上就会规避查询范围波及太多的库。
ptg2008
1 天前
对于分库分表,会根据唯一键通过算法(常用一致性哈希)将用户算到某个固定的库里面,这个用户的增删改查就只在这个库不会产生跨库事务(同一业务模块设计初要避免跨库事务);
对于即席数据的查询,一般是将数据同步到 ES 或者 clickhouse 或者 trino 等用于做专门的查询对于冷数据,
对于已经完成的订单或者交易公司内部基本都会有专门的归档平台,会将这些数据归档到冷库 做冷热分离, 你查询时会根据查询条件后端去冷库查询, 这时候就会比较慢点了,所以一般类似这种记录只会允许你查一年范围的
dxddd
1 天前
@irisdev 原理就是空间/资源换时间。单一实例,因为 CPU 内存 操作系统的限制,无论是数据库还是 JAVA 应用,吞吐量都是有上限的。所以人们发明了各种拆分工具,比如一次请求,从 DNS 解析->NGINX->多实例和服务化治理->数据库主从/读写分离/分库分表,都是在干这个事情。
pvnk1u
1 天前
不冲突啊,写入的时候可以根据数据取模进行分库分表,查询的时候也可以根据数据取模去各个库表里全都查出来,至于一些只有在单库单表里才能实现的功能,比如数据合并汇总这些,可以在查出来之后在代码逻辑里完成,无非多耗点内存的事,处理速度很快的
sardina
1 天前
分表分库的原则要用你们在业务里不会“交叉”的数据值做哈希来分,比如说你负责的生产模块,物料表应该需要有归属,比如属于某个 User ,就用 User 的 id 做哈希分,或者属于某个 Team 就用 team 的 id 做哈希去分
ifuture
1 天前
本质上就是分而治之,分的话,可以多维度的分,可以用地区、时间或者哈希,反正目的就是保证最终落在每个数据库的数据规模是相对有限的,比如在生成用户 id 时候,可以携带地区编号和时间戳信息,这样通过用户 id 就能快速定位到对应的库表,对于订单表这种数据规模更大的数据表,订单本质上是基于用户产生,为了保证某个用户产生的订单都在一个库表里面,完全可以用户 id 哈希后获得对应的订单库表,然后进行订单数据的存储和查询
Huelse
1 天前
本质上就是分机器,然后用中间件合起来,当作一个集群
huguang3320
1 天前
最近要做知识分享,也在学习分库分表,就像你说的,这个事不是一劳永逸的,涉及到事务的一致性,ID 一致性,还有就是在代码应用层上的聚合(不知道有些中间件是不是已经做好了),需要考虑的问题好像很多
chinafengzhao
1 天前
MIT 6.824 , 值得学一学
kingwang
1 天前
如果我的业务全在存储过程里,各位又会如何应对?
chutianyao
1 天前
如果只是 sql 数据库的话, 两种方案: mycat 或者 tidb 都可以.
mycat 有点老了, 是在分库上加了一个 porxy 层,跟使用单库没啥区别.我们订单、支付等很多库都是用它的, 稳定性还可以, 但高并发不建议使用.
tidb 稳定性不太行,我们遇到好几次故障了,还查不到原因. 可用性要求不高的话可以使用
chutianyao
1 天前
不过很多场景,特别是复杂的条件搜索,不会直接查数据库, 而是通过 binlog,再存一份 es,使用 es 来存储查询.
irisdev
1 天前
@chutianyao 老哥用 mycat 这种中间件会有事务问题吗,是不是一致性不太好保证,尤其高并发场景
chutianyao
1 天前
@irisdev 事务不垮库就没问题啊. 不知道你说的高并发是多大, 我们 qpm 约 3k 左右没啥问题.
irisdev
1 天前
@chutianyao 懂了,谢谢
promiser3d
1 天前
@chutianyao tidb 这么菜吗?他们也做好了好多年了。
heiya
1 天前
1.分库分表是有一些中间件能做的,按照现有数据及未来规划把已有的一张大表均匀的分散到一些实际小表上(比如按照 id 取模分成 32 、64 、1024 张物理表),查询时只需要查逻辑表就可以了。
2.分表之后可能会有效率问题,这取决于你的业务。有些查询很复杂,速度比较慢,流量一上来就会噶。这时候需要其他数据库对查询进行辅助,不走分表的数据。
angryfish
1 天前
1.大表查询,面向客户端他就不会涉及到很复杂的查询。基本上用的是用户 id 做分库分表了,所以问题不会很大的。
2.运营后台之类的做统计分析等复杂查询,数据可能后台算好结果的是 t+1 的。或者是多个分表冗余。
最后总结,就是能不分库分表,坚决不要分。总体的开发复杂度会提高很多
onepunch
1 天前
分享一下我的经验

1. 数据规模较大可以创建一个库,仅保留最近一段时间的数据(几个月或一年),这样满足了部分数据查询的需求,又控制了整体数据的规模,能够保证查询的性能
2. “下单记录”这样的功能一般都是默认查询当年,可以插叙指定年的数据。换句话说,历史数据一般都按年归档分表了
3. 有分析数据的需求,一般数据库查不动,需要考虑其他数据库或者大数据方案
4. 或者将物料相关接口内聚,独立成一个服务,对外提供接口查询数据。服务内部,再根据不同的场景选择不同的数据库来管理数据
taoohe
1 天前
1. 一般都不跨库查询,所以要问自己是不是拆库和拆表是否合理
2. 如果真的需要跨库一般解决方案是洗在 es 里查询。

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

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

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

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

© 2021 V2EX