ShardingJDBC 在查询的时候如果没有分表键,他怎么样?

典型回答 ShardingJDBC中有一个负责路由的路由引擎,对于带有分片键的SQL,根据分片键的不同可以划分为单片路由(分片键的操作符是等号)、多片路由(分片键的操作符是IN)和范围路由(分片键的操作符是BETWEEN)。 不携带分片键的SQL则采用广播路由。 根据SQL类型,广播路由又可以划分为全库表路由、全库路由、全实例路由、单播路由和阻断路由这5种类型。 一般来说,我们用的是比较多的其实就是 DML操作了,DML 操作的时候,主要做的就是全库表路由。 也就是说,当查询语句没有使用分片键时,ShardingJDBC 会将查询语句广播到所有的分片中执行。这意味着每个分片都会独立执行一次查询,然后 ShardingJDBC 会将各个分片的结果汇总并返回给应用。 举个例子,我们的逻辑表t_order,对应的物理表是t_order_01,t_order_02,t_order_03,t_order_00,而你的 SQL 是: 1 SELECT * FROM t_order WHERE user_name = "Hollis"; 那么他其实在执行时,执行的是以下 SQL: 1 2 3 4 5 6 7 SELECT * FROM t_order_00 WHERE user_name = "Hollis" UNION SELECT * FROM t_order_01 WHERE user_name = "Hollis" UNION SELECT * FROM t_order_02 WHERE user_name = "Hollis" UNION SELECT * FROM t_order_03 WHERE user_name = "Hollis"

March 22, 2026 · 1 min · santu

什么是分库?分表?分库分表?

典型回答 分库分表,是企业里面比较常见的针对高并发、数据量大的场景下的一种技术优化方案,所谓"分库分表",根本就不是一件事儿,而是三件事儿,他们要解决的问题也都不一样。 这三个事儿分别是"只分库不分表"、“只分表不分库”、以及"既分库又分表"。 分库主要解决的是并发量大的问题。因为并发量一旦上来了,那么数据库就可能会成为瓶颈,因为数据库的连接数是有限的,虽然可以调整,但是也不是无限调整的。所以,当你的数据库的读或者写的QPS过高,导致你的数据库连接数不足了的时候,就需要考虑分库了,通过增加数据库实例的方式来提供更多的可用数据库链接,从而提升系统的并发度。 **分表主要解决的是数据量大的问题。**假如你的单表数据量非常大,因为并发不高,数据量连接可能还够,但是存储和查询的性能遇到了瓶颈了,你做了很多优化之后还是无法提升效率的时候,就需要考虑做分表了。 那么,当你的数据库链接也不够了,并且单表数据量也很大导致查询比较慢的时候,就需要做既分库又分表了。 扩展知识 分库、分表、分库分表 分库主要解决的是并发量大的问题。比较典型的分库的场景就是我们在做微服务拆分的时候,就会按照业务边界,把各个业务的数据从一个单一的数据库中拆分开,分别把订单、物流、商品、会员等数据,分别放到单独的数据库中。 还有就是有的时候可能会需要把历史订单挪到历史库里面去。这也是分库的一种具体做法。 什么时候分表? 分表主要解决的是数据量大的问题。通过将数据拆分到多张表中,来减少单表的数据量,从而提升查询速度。 一般我们认为,单表行数超过 500 万行或者单表容量超过 2GB之后,才需要考虑做分库分表了,小于这个数据量,遇到性能问题先建议大家通过其他优化来解决。 PS:以上数据,是阿里巴巴Java开发手册中给出的数据,偏保守,根据实际经验来说,单表抗2000万数据量问题不大,但具体的数据里还是要看记录大小、存储引擎设置、硬件配置等。 从B+树的角度估算一下单表的数据量? 那如果,既需要解决并发量大的问题,又需要解决数据量大的问题时候。通常情况下,高并发和数据量大的问题都是同时发生的,所以,我们会经常遇到分库分表需要同时进行的情况。 所以,当你的数据库链接也不够了,并且单表数据量也很大导致查询比较慢的时候,就需要做既分库又分表了。 横向拆分和纵向拆分 谈及到分库分表,那就要涉及到该如何做拆分的问题。 **通常在做拆分的时候有两种分法,分别是横向拆分(水平拆分)和纵向拆分(垂直拆分)。**假如我们有一张表,如果把这张表中某一条记录的多个字段,拆分到多张表中,这种就是纵向拆分。那如果把一张表中的不同的记录分别放到不同的表中,这种就是横向拆分。 横向拆分的结果是数据库表中的数据会分散到多张分表中,使得每一个单表中的数据的条数都有所下降。比如我们可以把不同的用户的订单分表拆分放到不同的表中。 纵向拆分的结果是数据库表中的数据的字段数会变少,使得每一个单表中的数据的存储有所下降。比如我可以把商品详情信息、价格信息、库存信息等等分别拆分到不同的表中。 还有我们谈到的针对不同的业务做拆分成多个数据库的这种情况,其实也是纵向拆分的一种。 分表字段如何选择? 分表字段如何选择? 分表算法 分表算法都有哪些? 全局ID的生成 分表后全局ID如何生成? 分库分表的工具 在选定了分表字段和分表算法之后,那么,如何把这些功能给实现出来,需要怎么做呢? 我们如何可以做到像处理单表一样处理分库分表的数据呢?这就需要用到一个分库分表的工具了。 目前市面上比较不错的分库分表的开源框架主要有三个,分别是sharding-jdbc、TDDL和Mycat Sharding-JDBC 现在叫ShardingSphere(Sharding-JDBC、Sharding-Proxy和Sharding-Sidecar这3款相互独立的产品组成)。它定位为轻量级Java框架,在Java的JDBC层提供的额外服务。它使用客户端直连数据库,以jar包形式提供服务,无需额外部署和依赖,可理解为增强版的JDBC驱动,完全兼容JDBC和各种ORM框架。 开源地址:https://shardingsphere.apache.org TDDL TDDL 是淘宝开源的一个用于访问数据库的中间件, 它集成了分库分表, 读写分离,权重调配,动态数据源配置等功能。封装 jdbc 的 DataSource给用户提供统一的基于客户端的使用。 开源地址:https://github.com/alibaba/tb_tddl Mycat Mycat是一款分布式关系型数据库中间件。它支持分布式SQL查询,兼容MySQL通信协议,以Java生态支持多种后端数据库,通过数据分片提高数据查询处理能力。 开源地址:https://github.com/MyCATApache/Mycat2

March 22, 2026 · 1 min · santu

分库分表后会带来哪些问题?

典型回答 分库分表之后,会带来很多问题。 首先,做了分库分表之后,所有的读和写操作,都需要带着分表字段,这样才能知道具体去哪个库、哪张表中去查询数据。如果不带的话,就得支持全表扫描。 但是,单表的时候全表扫描比较容易,但是做了分库分表之后,就没办法做扫表的操作了,如果要扫表的话就要把所有的物理表都要扫一遍。 还有,一旦我们要从多个数据库中查询或者写入数据,就有很多事情都不能做了,比如跨库事务就是不支持的。 所以,分库分表之后就会带来因为不支持事务而导致的数据一致性的问题。 ✅常见的分布式事务有哪些? 其次,做了分库分表之后,以前单表中很方便的分页查询、排序等等操作就都失效了。因为我们不能跨多表进行分页、排序。 ✅分库分表后如何进行分页查询? 除此之外,还有一些其他的问题,比如二次分表的问题,一致性ID的问题等等。 ✅分库分表后,表还不够怎么办? 二次分表的问题可以用一致性哈希解决: 什么是一致性哈希? 分布式ID可以参考: ✅分布式ID生成方案都有哪些?

March 22, 2026 · 1 min · santu

分库分表的取模算法策略如何避免数据倾斜

典型回答 ✅什么是数据倾斜,会带来哪些问题?如何解决? 在上文中,我们介绍了什么是数据倾斜, 以及发生后如何解决。 分库分表时使用取模算法是一种常见的数据分片策略,它通过对某个字段的值进行取模运算来决定数据存储的目标库或表。然而,如果数据分布不均匀,简单的取模算法可能会导致某些数据库或表的负载明显高于其他,即数据倾斜问题。 但是,我们是不是可以在前期就想办法避免数据倾斜的问题呢?也是有办法的,可以采取以下几种策略: 选择合适分片键 选择合适的分片(分表)键是避免数据倾斜的关键。分片键应该是高度散列的,并且在业务操作中经常被用作查询条件。 例如,用户ID通常是一个好的分片键,因为它通常能保证数据分布的均匀性。但是当做分表的时候,买家ID肯定比卖家ID分片会出现倾斜的概率要低得多。毕竟一个买家的订单肯定不会有卖家的订单多。 复合分片 复合分片策略结合了多个分片键和/或多种分片方法。例如,可以先基于第一个分片键进行粗略分片,然后在每个粗略分片内部再根据第二个分片键进行细分。这种方法可以进一步细化数据分布,减少倾斜的风险。 例如说,对于支付单的表,按照付款方分片之后,发现有的付款方式企业账号,他的数据量很大,就会出现数据倾斜。 那么就可以针对付款方类型是企业的,再把"付款方ID+下单日期"组合在一起做一次分片。当然,这也会带来一个问题,就是下次查询的时候需要带上下单日期才行。但是我们前面的几篇分库分表的文章中讲过,我们可以通过基因法把分表结果组装到支付单号中,后续查询基于支付单号。 虚拟分片 虚拟分片意味着实际的物理分片数量远少于虚拟分片的数量。首先,基于一个较大的取模基数进行分片,将数据均匀分布到多个虚拟分片中,然后再将这些虚拟分片映射到实际的物理分片上。这种方法可以在一定程度上缓解数据倾斜的问题,因为即使某些键值分布不均,通过虚拟分片和映射也能实现较均匀的数据分布。 假设有100个虚拟分片,但实际只有10个物理分片。那么就是每个物理分片包含10个虚拟分片。 当一个数据项需要被存储时,我们首先根据某个键(比如用户ID)对100取模,决定将这个数据项放到哪个虚拟分片中。然后,这个虚拟分片会根据预先定义的映射关系被映射到一个物理分片上。这样,即使某些用户ID段的数据特别多,通过虚拟分片和映射也能较均匀地分布到所有的物理分片上。

March 22, 2026 · 1 min · santu

分表后全局ID如何生成?

涉及到分库分表,就会引申出分布式系统中唯一主键ID的生成问题,因为在单表中我们可以用数据库主键来做唯一ID,但是如果做了分库分表,多张单表中的自增主键就一定会发生冲突。那就不具备全局唯一性了。 那么,如何生成一个全局唯一的ID呢?有以下几种方式: UUID 很多人对UUID都不陌生,它是可以做到全局唯一的,而且生成方式也简单,但是我们通常不推荐使用他做唯一ID,首先UUID太长了,其次字符串的查询效率也比较慢,而且没有业务含义,根本看不懂。 基于某个单表做自增主键 多张单表生成的自增主键会冲突,但是如果所有的表中的主键都从同一张表生成是不是就可以了。 所有的表在需要主键的时候,都到这张表中获取一个自增的ID。 这样做是可以做到唯一,也能实现自增,但是问题是这个单表就变成整个系统的瓶颈,而且也存在单点问题,一旦他挂了,那整个数据库就都无法写入了。 基于多个单表+步长做自增主键 为了解决单个数据库做自增主键的瓶颈及单点故障问题,我们可以引入多个表来一起生成就行了。 但是如何保证多张表里面生成的Id不重复呢?如果我们能实现以下的生成方式就行了: 实例1生成的ID从1000开始,到1999结束。 实例2生成的ID从2000开始,到2999结束。 实例3生成的ID从3000开始,到3999结束。 实例4生成的ID从4000开始,到4999结束。 这样就能避免ID重复了,那如果第一个实例的ID已经用到1999了怎么办?那就生成一个新的起始值: 实例1生成的ID从5000开始,到5999结束。 实例2生成的ID从6000开始,到6999结束。 实例3生成的ID从7000开始,到7999结束。 实例4生成的ID从8000开始,到8999结束。 我们把步长设置为1000,确保每一个单表中的主键起始值都不一样,并且比当前的最大值相差1000就行了。 雪花算法 雪花算法也是比较常用的一种分布式ID的生成方式,它具有全局唯一、递增、高可用的特点。 雪花算法生成的主键主要由 4 部分组成,1bit符号位、41bit时间戳位、10bit工作进程位以及 12bit 序列号位。 时间戳占用41bit,精确到毫秒,总共可以容纳约69年的时间。 工作进程位占用10bit,其中高位5bit是数据中心ID,低位5bit是工作节点ID,做多可以容纳1024个节点。 序列号占用12bit,每个节点每毫秒0开始不断累加,最多可以累加到4095,一共可以产生4096个ID。 所以,一个雪花算法可以在同一毫秒内最多可以生成1024 X 4096 = 4194304个唯一的ID ✅什么是雪花算法,怎么保证不重复的?

March 22, 2026 · 1 min · santu

分表字段如何选择?

在分库分表的过程中,我们需要有一个字段用来进行分表,比如按照用户分表、按照时间分表、按照地区分表。这里面的用户、时间、地区就是所谓的分表字段。 那么,在选择这个分表字段的时候,一定要注意,要根据实际的业务情况来做慎重的选择。 比如说我们要对交易订单进行分表的时候,我们可以选择的信息有很多,比如买家Id、卖家Id、订单号、时间、地区等等,具体应该如何选择呢? 通常,如果没有特殊的诉求,比如按照月度汇总、地区汇总等以外,我们通常建议大家按照买家Id进行分表。因为这样可以避免一个关键的问题那就是——数据倾斜(热点数据)。 ✅什么是数据倾斜,会带来哪些问题?如何解决? 买家还是卖家 首先,我们先说为什么不按照卖家分表? 因为我们知道,电商网站上面是有很多买家和卖家的,但是,一个大的卖家可能会产生很多订单,比如像苏宁易购、当当等这种店铺,他每天在天猫产生的订单量就非常的大。如果按照卖家Id分表的话,那同一个卖家的很多订单都会分到同一张表。 那就会使得有一些表的数据量非常的大,但是有些表的数据量又很小,这就是发生了数据倾斜。这个卖家的数据就变成了热点数据,随着时间的增长,就会使得这个卖家的所有操作都变得异常缓慢。 但是,买家ID做分表字段就不会出现这类问题,因为不太容易出现一个买家能把数据买倾斜了。 但是需要注意的是,我们说按照买家Id做分表,保证的是同一个买家的所有订单都在同一张表 ,并不是要给每个买家都单独分配一张表。 我们在做分表路由的时候,是可以设定一定的规则的,比如我们想要分1024张表,那么我们可以用买家ID或者买家ID的hashcode对1024取模,结果是0000-1023,那么就存储到对应的编号的分表中就行了。 卖家查询怎么办 如果按照买家Id进行了分表,那卖家的查询怎么办,这不就意味着要跨表查询了吗? 首先,业务问题我们要建立在业务背景下讨论。电商网站订单查询有几种场景? 1、买家查自己的订单 2、卖家查自己的订单 3、平台的小二查用户的订单。 首先,我们用买家ID做了分表,那么买家来查询的时候,是一定可以把买家ID带过来的,我们直接去对应的表里面查询就行了。 那如果是卖家查呢?卖家查询的话,同样可以带卖家id过来,那么,我们可以有一个基于binlog、flink等准实时的同步一张卖家维度的分表,这张表只用来查询,来解决卖家查询的问题。 本质上就是用空间换时间的做法。 不知道大家看到这里会不会有这样的疑问:同步一张卖家表,这不又带来了大卖家的热点问题了吗? 首先,我们说同步一张卖家维度的表来,但是其实所有的写操作还是要写到买家表的,只不过需要准实时同步的方案同步到卖家表中。也就是说,我们的这个卖家表理论上是没有业务的写操作,只有读操作的。 所以,这个卖家库只需要有高性能的读就行了,那这样的话就可以有很多选择了,比如可以部署到一些配置不用那么高的机器、或者其实可以干脆就不用MYSQL,而是采用HBASE、PolarDB、Lindorm等数据库就可以了。这些数据库都是可以海量数据,并提供高性能查询的。 还有呢就是,大卖家一般都是可以识别的,提前针对大卖家,把他的订单,再按照一定的规则拆分到多张表中。因为只有读,没有写操作,所以拆分多张表也不用考虑事务的问题。 这里说的没有写指的是不会主动操作这张卖家表做更新,他的数据都是从买家表同步过来的,这个同步的事务在买家表已经处理过了,卖家表只需要负责同步。 卖家更新数据也一样,都是基于订单号更新的,订单号上面是带来分表信息的,直接到买家表去更新,然后同步到卖家表。 订单查询怎么办 上面说的都是有买卖家ID的情况,那没有买卖家ID呢?用订单号直接查怎么办呢? 这种问题的解决方案是,在生成订单号的时候,我们一般会把分表结果编码到订单号中去,因为订单生成的时候是一定可以知道买家ID的,那么我们就把买家ID的路由结果比如1023,作为一段固定的值放到订单号中就行了。这就是所谓的**“基因法”** 这样按照订单号查询的时候,解析出这段数字,直接去对应分表查询就好了。 至于还有人问其他的查询,没有买卖家ID,也没订单号的,那其实就属于是低频查询或者非核心功能查询了,那就可以用ES等搜索引擎的方案来解决了。就不赘述了。

March 22, 2026 · 1 min · santu

分区和分表有什么区别?

典型回答 数据库中数据量过多,表太大的时候,不仅可以做分库分表,还可以做表分区,分区和分表类似,都是按照一定的规则将一张大表进行分解。 听上去好像也差不多,不就是将表拆分吗?那具体有什么差别呢? 主要是分区和分表后数据的数据存储方式有变化。 在Innodb中(8.0之前),表存储主要依赖两个文件,分别是.frm文件和.ibd文件。.frm文件用于存储表结构定义信息,而.ibd文件则用于存储表数据。 假如我们有一张users表,想要对他进行分区和分表,区别如下: MySQL InnoDB存储引擎在分区表时,会将每一个分区分别存放在一个单独的 .ibd 文件中,所有的 .ibd 文件组合构成表的物理结构,即 Table Space。 对于上面分区的 users表,存储时会在 MySQL 的 data 目录下创建一个用户名+表名+分区名.ibd 的文件(如:users_p1.ibd),用来存储 users 表中第一个分区的数据,同样会有 users_p2.ibd 和 users_p3.ibd 来存储第二和第三个分区的数据: 1 2 3 4 5 users_p1.ibd users_p2.ibd users_p3.ibd users_p4.ibd users.frm MySQL InnoDB存储引擎在分表时,会将每一个分表分别存放在一个单独的 .frm 文件中,所有的 .frm 文件组合构成表的逻辑结构,即 Table Definition。 对于上面分表的users表,存储时会在 MySQL 的data目录下创建后缀名为“users_1.frm”的表格文件,存储 users 表中第一个分表的数据,同样会有 users_2.frm 和 users_3.frm 来存储第二和第三个分表的数据: 1 2 3 4 5 6 7 8 users_1.ibd users_1.frm users_2.ibd users_2.frm users_3.ibd users_3.frm users_4.ibd users_4.frm 在做了分区后,表面是还是只有一张表,只不过数据保存在不同的位置上了(同一个.frm文件),在做数据读取的时候操作的表名还是users表,数据库会自己去组织各个分区的数据。 ...

March 22, 2026 · 1 min · santu

分表算法都有哪些?

如何基于这个分表字段来准确的把数据分表到某一张表中? 这就是分表算法要做的事情了,但是不管什么算法,我们都需要确保一个前提,那就是同一个分表字段,经过这个算法处理后,得到的结果一定是一致的,不可变的。 通常情况下,当我们对order表进行分表的时候,比如我们要分成128张表的话,那么得到的128表应该是:order_0000、order_0001、order_0002…..order_0126、order_0127 通常的分表算法有以下几种: 直接取模 在分库分表时,我们是事先可以知道要分成多少个库和多少张表的,所以,比较简单的就是取模的方式。 比如我们要分成128张表的话,就用一个整数(可以是你的某个业务单据号的值或者他的hashcode的值,比如用户id,或者订单号之类的)来对128取模就行了,得到的结果如果是0002,那么就把数据放到order_0002这张表中。 按照关键字 有的时候,我们在分表的时候,可以给予一定的关键字做拆分,比如按照时间,比如某个月份或者年份的数据单独放在某一个表中,或者可以按照地区分表也比较常见。 Hash取模 那如果分表字段不是数字类型,而是字符串类型怎么办呢?有一个办法就是哈希取模,就是先对这个分表字段取Hash,然后在再取模。 但是需要注意的是,Java中的hash方法得到的结果有可能是负数,需要考虑这种负数的情况。 一致性Hash 前面两种取模方式都比较不错,可以使我们的数据比较均匀的分布到多张分表中。但是还是存在一个缺点。 那就是如果需要扩容二次分表,表的总数量发生变化时,就需要重新计算hash值,就需要涉及到数据迁移了。 为了解决扩容的问题,我们可以采用一致性哈希的方式来做分表。 ✅什么是一致性哈希? 一致性哈希可以按照常用的hash算法来将对应的key哈希到一个具有2^32次方个节点的空间中,形成成一个顺时针首尾相接的闭合的环形。所以当添加一台新的数据库服务器时,只有增加服务器的位置和逆时针方向第一台服务器之间的键会受影响。

March 22, 2026 · 1 min · santu

什么是数据倾斜,会带来哪些问题?如何解决?

典型回答 数据倾斜是指在分布式计算或数据库环境中,数据分布不均匀的现象。在理想的分布式系统中,数据和计算负载应该均匀分布在所有节点上。然而,由于各种原因,某些节点可能承载比其他节点更多的数据或计算负载,这就是数据倾斜。 比如一个系统中共有500万数据,但是属于同一个商家的数据就有400万,那么如果数据库按照商家做分库分表,就会导致出现严重的数据倾斜。 一般来说,数据倾斜发生在分库分表的场景中比较多,因为主要是因为分表字段选择的不够合适导致的。你比如说我之前做过一个定价系统,然后我们是按照付款方做的分库分表。原来都挺好的,同一个用户的付款也不会有什么特别多的数据,但是后来出现了一种机构付款的情况,有一个商户作为付款方了,那么就会导致这个商户的数据有很多,就会大量的堆积在同一张表中,就导致这个表数据量剧增。 数据倾斜主要会带来以下几个问题: 性能瓶颈:数据倾斜可能导致某些节点的负载明显高于其他节点,从而成为整个系统的性能瓶颈。 比如在Redis中,出现的热key问题,其实也是数据倾斜的一种具体情况,那么就会导致这个节点的负载非常高。 资源利用不均:导致资源利用不均衡,一部分节点可能过载,而其他节点则闲置。 查询效率低下:在数据库中,数据倾斜可能导致查询效率低下,特别是在执行JOIN操作或聚合查询时。 比如数据库分表后数据倾斜,就会使得分表的效果并不明显,单表的数据量还是可能会很大,导致查询速度变慢。 影响其他业务:某些数据倾斜会导致查询比较慢,这样不仅使这个业务有影响,和他在同一张表中的其他业务的数据也会有影响。 比如某个小商家和一个大商户的数据在同一张表,那么它的查询也会变慢。 所以,我们在做分库分表的时候,在选择分表字段的时候,一定要考虑数据倾斜的问题,尽量选择那种不会有聚集性数据的字段来做分表字段,如订单表,尽量选择买家ID。 如何解决 要解决数据倾斜的问题,其实和解决单表数据量大是同样的方案,无非就是把数据再拆分一下,分散数据量。 拆分 比如在Redis中,为了解决热key的问题,可以采用Cluster模式,把一个热key拆分到多个实例上存储。 ✅什么是热Key问题,如何解决热key问题 还有就是在分库分表场景,那就是做一下二次分表。 比如我之前提的那个定价记录表付款方严重倾斜的问题,为了解决它,我修改了一下我的路由算法。如果付款方式机构类型,那么我在分表时就会把时间因素考虑进去。基于时间在做一次分表。 1 2 3 4 5 6 7 8 9 10 //为了解决机构账户的热点问题,这里对于付款方是机构的情况做特殊处理,拼接时间戳后进行分表 switch (customerTypeEnum) { case INSTITUTION_NAME: externalId = quotationDO.getPayerId() + DateUtils.truncate(quotationDO.getBizTime(), Calendar.SECOND).getTime(); break; default: externalId = quotationDO.getPayerId(); } //这里再基于externalId做哈希取模 或者如果付款方一样,那么就基于收款方再做一次分表。这样后续每一次的插入、查询、更新都用同一个分表算法就行了。算法内部自己把这个逻辑包掉就可以了。 只不过在查询的时候,就需要的信息就会多一些,以前可能根据一个付款方就够查询了,因为只需要这一个字段就能知道会路由到哪张表,但是修改之后,就需要付款方、付款方类型以及时间戳三个字段了。就会使得查询更加麻烦一些,当然也不是所有查询都需要, 只有热点账户相关的才需要,非热点的并不需要。 隔离 除了做二次分表或者数据拆分以外。还有一个办法,为了降低因为数据倾斜而带来的影响,有的时候我们也会采取物理隔离的方式。 ...

March 22, 2026 · 1 min · santu

分库分表后,表还不够怎么办?

典型回答 有的时候,当我们对数据库做了分库分表后,因为最初的预估数据不够准确,导致后续数据增长很快,表不够了,那么遇到这种情况该怎么办呢? 首先,我们应该尽量避免这种情况的发生,在第一次决定分表的时候,就尽可能根据当前的业务增长量预估一下未来可能需要存储的数据量,并且最好一定的buffer,让这个分表尽可能够,避免出现不够的情况。 比如我们线上分表基本都是256、512、1024这样分的。 其次,如果真的后面就不够了,其实也没啥特别好的办法,要么就通用其他的手段来减少数据量,比如我们之前提到过的数据归档等。 ✅如果单表数据量大,只能考虑分库分表吗? 那还有,就只剩一条路了,那就是二次分表,即原来的128张不够,那么就需要重新分成256张表。这个过程和第一次从单表分成128张表过程差不多。 涉及到分表算法的更新,数据的迁移等。其中最关键的就是如何无损、无缝的做数据迁移了: ✅如何做平滑的数据迁移? 另外,还有一个值得考虑的,就是如果最开始用的是一致性hash的算法进行分表路由,那么在做二次分表的时候,数据迁移的成本就会低很多,因为影响的节点可能没那么多。 ✅什么是一致性哈希? 所以,总结一下,就是要么提前多分点、要么就是想办法减少数据量,如做数据归档,要么就是重新分,然后做数据迁移。如果提前考虑过的话,用了一致性哈希的话会影响更小一点。除了这些,也没啥更好的办法了。

March 22, 2026 · 1 min · santu

留言给博主