关于分库分表的一点疑惑
平时做的项目都比较小,一般都是几台应用服务器+几台数据库服务器,虽然也有数据库拆分,但基本上都是把不同业务的表放在不同库中,比如一个 erp 系统,将财务相关的表放在某台服务器的某个库中,将仓库相关的表放在某台服务器的某个库中,没有拆分到更细的颗粒度,比如物料表,快上亿条数据了,也没有将这一张表拆分成不同表或者到不同库中。
目前即使是这样也给写代码带来了一些麻烦,比如我负责生产模块,但是有时候要查一些物料数据,这时候就不可避免地要跨库查数据,这样我还可以理解。但是如果有一天物料表要拆分成两张表或者到两个库中,那我写 sql 时岂不是要一样的语句写两遍然后 union 一下了?联想到那些大厂,比如淘宝,所有用户的“足迹”,就是浏览记录,至少得有百亿条数据了吧?这种业务是怎么处理的呢...应用服务器我可以理解,可以 cdn ,可以负载均衡,反正运行的是一套代码。但是数据库我就理解不了了,就算是一个简单的查询,“根据用户得到下单记录”,那也得全表查询吧?难不成这张订单表是单表?不现实。如果这张订单表被拆过,那淘宝的程序员在写代码的时候要考虑各个子库各个子表的情况吗?那不得累死。还是说“数据库集群”(只听过没概念...)可以像服务器集群一样屏蔽连接,程序员写代码就好了?不过在我理解中,服务器集群部署的是代码,转发到哪一台都可以,数据库集群里面的数据都是不一样的,那如果要屏蔽细节提供跟单体数据库一样的服务,内部肯定也通过网络通信然后统一提供给用户,这样感觉会不会对效率也有影响?感觉这些大公司的应用速度还是很快的,尤其是拼多多,感觉查订单记录就跟查几万几十万的表一样。
因为这块懂得太少,表达地比较乱,也没法专业地表达,见谅..但意思应该表达出来了,这个疑问困扰我很久了,有没有明白的说两句,感谢
分库分表不是中间件干的活吗, 好多大价钱买中间件就是用来自动分库分表的
😳还是在应用层解决吗,还以为数据库自带什么机制可以提供单体类似的数据库链接
分实时和非实时吧, 你看订单都是最近 xxx 订单是查看的, 这部分进行分表|分区, 按照用户维度来划分, 太久的数据就直接存到另一个地方
分表你可以简单的在代码层面分(通过用户 id hash), 不过现在很多云数据库都有中间件, 你连接的数据库并不是数据, 而是中间件, 然后中间件来帮你实现读写分离, 智能分表
还有另一个方案就是, 订单数据冗余存储, 你给用户看的是一个分表, 给财务看的是另一个分表
明白了,谢谢。我把问题想简单了,没有一劳永逸的方案
同好奇
推荐一本书《数据密集型应用系统设计》
- 较早的数据库,例如 MySQL 这种对外提供的表概念就是最小化的逻辑单位的情况。通过特定的第三方中间件去实现分库分表,例如在数据库集群上包装入口,或者使用特定的数据库驱动库去链接数据库。本质上是通过特定的逻辑实现自动分库分表
以查询用户的订单为例。设定所有用户的 UID 前两位或者前三位均匀分布在 00-99 或者 000-999 ,然后针对用户的订单(或者任意的用户数据)的操作必须带上用户 UID 信息。中间件拦截这个 UID 字段,并且自动解析,路由到对应的分库分表
虽然使用上是几乎无感的,但是作为研发要知道实际下面可能数据路由到了不同的库表(甚至可能会路由到不同的物理数据库集群中)。这点在事务中要尤其注意
- 现代的数据库(?)在底下存储的时候,除了有表的概念,有些会进一步细分 region ,或者叫数据块的逻辑单位。数据实际存储在 region 中,表只是 region 的逻辑集合,region 通过主键自动或者手动进行划分,对数据进行分割存储
相比于分库分表这样的作法理论上可以保持单表的无限扩容,并且可以保证数据在同一个数据库的逻辑概念中(不至于要分库)
哥们你这是 ai 还是手打的。。我已经分不清了。现代数据库指分布式数据库吗
当然是手打的,这哪有 ai 那味儿( xs
现代数据库并不是一个精确的概念,只是我自己想的一个词,用来代指理念上设计更现代的的数据库,比如内置的 region 的设计?
现代数据库也不等同于分布式,根据适用场景现代数据库也有单点(大部分现代分布式数据库都可以同时单点部署和分布式部署)和“嵌入式”数据库(比如有名的 duckdb )
我是能不分就不分,复杂度嘎嘎增加,尽量采用归档,十亿分区,百亿分表
数据库有分区表 把这些分表的逻辑写在数据库中了
哦,我觉得可以问下 AI 或者搜索下,比如 www.oceanbase.com/solution/sharding
这个 region 的概念会泄露到 SQL 中吗?是否相当于内置了中间件,有现代的数据库 的具体代表性产品 吗?
我知道的 tidb 是有 region 的
#2 分布式数据库基本都是透明 sharding 的
1 代码实现 就是 sql 写各种 union all
2 框架实现 相当于封装了一层,本质可能也是 union all
3 中间件 相当于把框架抽出来独立做了一个服务
4 数据库 几乎也是 union all
我这里说的 union all 可能不限于是 sql 语句,就是表达一个汇总的含义。本质上就是把一块大资源拆成若干个小资源。以提升 IO 性能和查询性能。
我一开始不理解这样"union"速度真的会快很多吗,因为在 sql 里面写 union 应该是串行查的。但是昨晚琢磨了一下,一个两千万的表,索引没建好可能查的很慢,但是拆成 5 个 200 万的表,,如果可以做到并行查,并行查然后汇总的话,也许某些场景下,查询是会快很多,但是如 2 楼所说,也不是什么银弹,并不是分布式或是分库分表就一定可以高效解决数据量大慢的问题,原理还是不太懂,但大概知道是这么个意思了,不知道理解对不对
一般根据查询条件就能定位到对应的表了,比如 userId = 123 ,算法算完就能定位到是在 order 表的第五张上,所以最后还是单表查询,最后实际拼接的数据库的语句是 select * from order5 where xxxxx
努力卷去大公司混两三年,你对这个世界的理解都不一样了
刚毕业时大公司干过一段时间,不过干的前端。现在能力不够没机会去大公司了~
我对这块也有类似的疑问。我自己的感觉是下面的实现很可能还真就是大力出奇迹,我们往往低估数据库的能力,就像我们容易从身边的生活经验去估计工业材料的强度一样。
另外很多大型应用从 UX 设计上就会规避查询范围波及太多的库。
对于分库分表,会根据唯一键通过算法(常用一致性哈希)将用户算到某个固定的库里面,这个用户的增删改查就只在这个库不会产生跨库事务(同一业务模块设计初要避免跨库事务);
对于即席数据的查询,一般是将数据同步到 ES 或者 clickhouse 或者 trino 等用于做专门的查询对于冷数据,
对于已经完成的订单或者交易公司内部基本都会有专门的归档平台,会将这些数据归档到冷库 做冷热分离, 你查询时会根据查询条件后端去冷库查询, 这时候就会比较慢点了,所以一般类似这种记录只会允许你查一年范围的
原理就是空间/资源换时间。单一实例,因为 CPU 内存 操作系统的限制,无论是数据库还是 JAVA 应用,吞吐量都是有上限的。所以人们发明了各种拆分工具,比如一次请求,从 DNS 解析->NGINX->多实例和服务化治理->数据库主从/读写分离/分库分表,都是在干这个事情。
不冲突啊,写入的时候可以根据数据取模进行分库分表,查询的时候也可以根据数据取模去各个库表里全都查出来,至于一些只有在单库单表里才能实现的功能,比如数据合并汇总这些,可以在查出来之后在代码逻辑里完成,无非多耗点内存的事,处理速度很快的
分表分库的原则要用你们在业务里不会“交叉”的数据值做哈希来分,比如说你负责的生产模块,物料表应该需要有归属,比如属于某个 User ,就用 User 的 id 做哈希分,或者属于某个 Team 就用 team 的 id 做哈希去分
麻烦请教大家一个问题,有台机器,没有使用 swap ,但是内存不够用了,,cached 有点高,导致磁盘 io 读会高,,我理解 cached 是读缓存,如果不够了,就需要不断…
在 Docker基础技术:Linux Namespace(上篇)中我们了解了,UTD、IPC、PID、Mount 四个namespace,我们模仿Docker做了一个相当相当山…
2009年10月06日,GDB7.0正式发布,新的版本你可以在这里下载。本次版本,不但有大家所关注的《GDB回溯调试技术》,同样还有其它大量的新特性,和对新平台的支持。 新版的…