分库分表方案对比

article/2025/4/24 10:05:01

房晓乐(葱头巴巴),PingCAP 资深解决方案架构师,前美团数据库专家、美团云 CDS 架构师、前搜狗、百度资深 DBA,擅长研究各种数据库架构,NewSQL 布道者。

原文链接:https://dbaplus.cn/news-11-1854-1.html

一、分库分表的背景

在谈论数据库架构演变和优化时,我们经常会听到分片、分库分表(Sharding)这样的关键词,在很长一段时间内,在各个公司、各中技术论坛里都很热衷谈论各种分片方案,尤其是互联网非常普及的 MySQL 数据库。但对笔者来说,分片、分库分表并不是一门创新技术,也不是一个好方案,它只是由于数据体系结构的限制而做的无奈之举,所以后来在听到这些词时,对笔者来说,更大意义在于感觉到朋友的公司业务量在快速增长,而对这个方案本身,其实有非常多问题。

 

二、分表的根本原因

 

以 MySQL 为例,分库分表从阶段应该拆分为分表、分库,一般来说是先进行分表,分表的原动力在于  MySQL 单表性能问题,相信大家都听说过类似这样的话,据说 MySQL 单表数据量超过 N 千万、或者表 Size 大于 N十G 性能就不行了。这个说法背后的逻辑是数据量超过一定大小,B+Tree 索引的高度就会增加,而每增加一层高度,整个索引扫描就会多一次 IO 。整个逻辑有一定道理,而从笔者的经验来看,其实更关键在于应用本身的使用,如果多数是索引命中率很高的点查或者小范围查,其实这个上限还很高,我们维护的系统里超过10亿级的表很常见。但正是由于业务的不可控,所以大家往往采取比较保守的策略,这就是分表的原因。

 

三、分库+分表的根本原因

 

 

分库主要由于 MySQL 容量上,MySQL 的写入是很昂贵的操作,它本身有很多优化技术,即使如此,写入也存在放大很多倍的现象。同时 MySQL M-S 的架构虽然天然地支持读流量扩展,但由于 MySQL 从库复制默认采用单线程的 SQL thread 进行 Binlog 顺序重放,这种单线程的从库写入极大地限制整个集群的写入能力,(除非不在意数据延迟,而数据延迟与否直接影响了读流量的可用性)。MySQL 基于组提交的并行复制从某种程度上缓解了这个问题,但本质上写入上限还是非常容易达到(实际业务也就 小几千 的 TPS ) 。说到这,目前有一些云 RDS 通过计算与存储分离、log is database 的理念来很大程度解决了写入扩大的问题,但在这之前,更为普遍的解决方案就是把一个集群拆分成 N 个集群,即分库分表(sharding)。为了规避热点问题,绝大多数采用的方法就是 hash 切分,也有极少的范围、或者基于 Mapping 的查询切分。

 

四、Sharding + Proxy

 

既然做了分表,那数据的分发、路由就需要进行处理,自下而上分为三层,分别 DB 层、中间层、应用层。DB 层实现,简单来说就是把路由信息加入到某个 Metedata 节点,同时加上一些诸如读写分离、HA 整合成一个 DB 服务或者产品,但这种方案实现复杂度非常高,有的逐步演变成了一种新的数据库,更为常见的是在中间层实现,而中间层又根据偏向 DB 还是偏向应用分为 DB proxy 和 JDBC proxy。

 

图:Sharding + Proxy

 

五、DB proxy or JDBC proxy

 

DB proxy、JDBC proxy 业内有很多种,很多都是开源的,我们简单汇总了常见的一些产品,如下图表。下面我们各找一些进行下对比,只讨论两种方案的优缺点,为了不必要的麻烦,本文不具体讨论哪个产品的优缺点。

 

实现方案业界组件原厂功能特性备注
DB proxy-based 多语言支持Atlas360读写分离、静态分表 
Meituan Atlas美团读写分离、单库分表目前已经在原厂逐步下架。
Cobar阿里(B2B)Cobar 中间件以 Proxy 的形式位于前台应用和实际数据库之间,对前台的开放的接口是 MySQL 通信协议开源版本中数据库只支持 MySQL,并且不支持读写分离。
MyCAT阿里是一个实现了 MySQL 协议的服务器,前端用户可以把它看作是一个数据库代理,用 MySQL 客户端工具和命令行访问,而其后端可以用MySQL 原生协议与多个 MySQL 服务器通信MyCAT 基于阿里开源的 Cobar 产品而研发
Heisenberg百度热重启配置、可水平扩容、遵守 MySQL 原生协议、无语言限制。 
KingshardKingshard由 Go 开发高性能 MySQL Proxy 项目,在满足基本的读写分离的功能上,Kingshard 的性能是直连 MySQL 性能的80%以上。 
JDBC - based 支持多 ORM 框架,一般有语言限制。TDDL阿里淘宝动态数据源、读写分离、分库分表TDDL 分为两个版本, 一个是带中间件的版本, 一个是直接 JAVA library 的版本。
Zebra美团点评实现动态数据源、读写分离、分库分表、CAT监控功能齐全且有监控,接入复杂、限制多。
MTDDL美团点评动态数据源、读写分离、分布式唯一主键生成器、分库分表、连接池及SQL监控 
DB - based 解决方案Vitess谷歌、Youtube集群基于ZooKeeper管理,通过RPC方式进行数据处理,总体分为,server,command line,gui监控 3部分Youtube 大量应用
DRDS阿里DRDS(Distributed Relational Database Service)专注于解决单机关系型数据库扩展性问题,具备轻量(无状态)、灵活、稳定、高效等特性,是阿里巴巴集团自主研发的中间件产品。逐渐下沉为DB服务

 

图:常见的Proxy

 

DB proxy

 

DBproxy 高度依赖网络组件,它需要诸如 LVS/F5 等 VIP 来实现流量的负载均衡,如果跨 IDC,还依赖诸如 DNS 进行IDC 分发。同时部分 DBproxy 对 Prepare 这类操作支持不友好,所以它的问题概括来说:

 

  • 链路过长,每层都会增加响应时间

  • 网络单点,并且往往是整个公司层面的单点

  • 部分产品对Prepare 应用不友好,需要绑定 connection 信息

 

JDBC proxy

 

JDBC Proxy 最大的问题是违背了 DB 透明的原则,它需要对不同的语言编写 Driver,概括来说:

 

  • 语言限制,总会遭到一批 RD 同学的吐槽 “世界上最好的语言竟然不支持!”

  • 接入繁琐

  • DB 不透明

 

 

图:DB proxy VS JDBC proxy

 

六、Sharding+Proxy成本汇总

 

 

Sharding + Proxy 本质上只解决了一个问题,那就是单机数据容量问题,但它有哪些成本呢?前面提了每种 proxy 都有比较大的硬伤,我们再把分库分表拉上,一起整理这个方案的成本。

 

1、应用限制

 

  1. Sharding 后对应用和 SQL 的侵入都很大,需要 SQL 足够简单,这种简单的应用导致 DB 弱化为存储。

  2. SQL 不能跨维度 join、聚合、子查询等。

  3. 每个分片只能实现 Local index,不能实现诸如唯一键、外键等全局约束。

 

2、Sharding 业务维度选择

 

  1. 有些业务没有天然的业务维度,本身选择一个维度就是个问题。

  2. 大部分业务需要多维度的支持,多维度的情况下。

 

  1. 哪个业务维度为主?

  2. 其它业务维度产生了数据冗余,如果没有全局事务的话,很难保证一致性,全局事务本身实现很难,并且响应时间大幅度下降,业务相互依赖存在重大隐患,于是经常发生“风控把支付给阻塞了”的问题。

  3. 多维度实现方式,数据库同步还是异步?同步依赖应用端实现双写,异步存在实效性问题,对业务有限制,会发生“先让订单飞一会的问题”。

  4. 多维度数据关系表(mapping)维护。

 

3、Sharding key 选择(非业务维度选择)

 

  1. 非业务维度选择,会存在“我要的数据到底在那个集群上”的问题。

  2. 业务维度列如何选择 Sharding key ?

  3. 热点如何均摊,数据分布可能有长尾效应。

 

4、Sharding 算法选择

 

  1. Hash 算法可以比较好的分散的热点数据,但对范围查询需要访问多个分片。反之 Range 算法又存在热点问题。所以要求在设计之初就要清楚自己的业务常用读写类型。

  2. 转换算法成本很高。

 

5、高可用问题

 

  1. 高可用的扩散问题(一个集群不可用,整个业务“不可用”)。

  2. 如何应对脑裂的情况?

  3. MGR 多主模式数据冲突解决方案不成熟,基本上还没公司接入生产系统。

  4. PXC 未解决写入容量,存在木桶原则,降低了写入容量。

  5. 第三方依赖,MHA(判断主库真死、新路由信息广播都需要一定的时间成本) 最快也需要 15s。

  6. 虽然有 GTID,仍然需要手工恢复。

 

6、数据一致性(其实这个严格上不属于分库分表的问题,但这个太重要了,不得不说)

 

  1. MySQL 双一方案( redo、binlog 提交持久化) 严重影响了写入性能。

  2. 即使双一方案,主库硬盘挂了,由于异步复制,数据还是会丢。

  3. 强一致场景需求,比如金融行业,MySQL 目前只能做到双一+半同步复制,既然是半同步,随时可能延迟为异步复制,还是会丢数据。

  4. MGR ?上面说过,多写模式问题很多,距离接入生产系统还很远。

  5. InnoDB Cluster ?先搞出来再说吧。

 

7、DB Proxy

 

  1. 依赖网络层(LVS)实现负载均衡,跨 IDC 依赖 DNS,DNS + LVS + DBproxy + MySQL 网络链路过长,延迟增加、最重要的是存在全公司层面网络单点。

  2. 部分产品对 Prepare 不友好,需要绑定 connection。

 

8、JDBC Proxy

 

  1. 语言限制,需要单独对某语言写 Driver,应用不友好。

  2. 并未实现 DB 层的透明使用。

 

9、全局 ID

 

  1. 很简单的应用变成了很复杂的实现。

  2. 采用 MySQL 自增 ID,写入扩大,单机容量有限。

  3. 利用数据库集群并设置相应的步长,绝对埋坑的方案。

  4. 依赖第三方组件,Redis Sequence、Twitter Snowflake ,复杂度增加,还引入了单点。

  5. Guid、Random 算法,说好的连续性呢?还有一定比例冲突。

  6. 业务属性字段 + 时间戳 + 随机数,冲突比例很高,依赖 NTP 等时间一致服务。

 

10、Double resource for AP

 

  1. 同样的数据需要双倍的人力和产品。

  2. 产品的重复,Hadoop、Hive、Hbase、Phoenix。

  3. 人力的重复。

  4. 数据迁移的复杂实现,Canal、databus、puma、dataX ?

  5. 实时查询?普遍 T+1 查询。

  6. TP 业务表变更导致 AP 业务统计失败,“老板问为啥报表显示昨天订单下降这么多,因为做个了 DDL。”

 

11、运维友好度 (DDL、扩容等)

 

  1. 运维的复杂性是随着机器数量指数级增长的,Google 在 F1 之前维护了一个 100 多个节点的 MySQL sharding 就痛得不行了,不惜重新写了一个 Spanner 和 F1 搞定这个问题。

  2. 传统 RDBMS 上 DDL 锁表的问题,对于数据量较大的业务来说,锁定的时间会很长,如果使用 pt-osc、gh-ost 这样第三方工具来实现非阻塞 DDL,额外的空间开销会比较大,另外仍然需要人工的介入确保数据的一致性,最后切换的过程系统可能会有抖动,pt-osc 还需要两次获取 metalock,虽然这个操作本事很轻量,可糟糕的是如果它被诸如 DDL的锁阻塞,它会阻塞所有的 DML,于是悲剧了。

 

12、与原有业务的兼容性

 

  1. 时间成本,如果业务一开始设计时没有考虑分库分表或者中间件这类的方案,在应对数据量暴增的情况下匆忙重构是很麻烦的事情。

  2. 技术成本,如果没有强有力和有经验的架构师,很难在业务早期做出良好的设计,另外对于大多数非互联网行业的开发者来说更是不熟悉。

 

13、Sharding 容量管理

 

  1. 拆分不足,需要再次拆分的问题,工作量巨大。

  2. 拆分充足,大部分业务增长往往比预期低很多,经常发生“又被 PM 妹纸骗了,说好的百万级流量呢”的问题,即时业务增长得比较好,往往需要一个很长的周期,机器资源浪费严重。

 

14、运维成本,人力成本

 

不解释,SRE、DBA 兄弟们懂的。

 

图:sharding 成本汇总

 

七、总结

 

 

分库分表为了解决一个问题,引入了很多成本,从长久看这种方案会逐步被新的解决方案替代。目前看来,解决的思路主要分为两个方向:

 

  • 第一个思路既然分库的原动力主要是单实例的写入容量限制,那么我们可以最大程度地提升整个写入容量,云计算的发展为这种思路提供了新的可能,以 AWS Aurora 为代表 RDS ,它以  Log is database 为理念,将复杂的随机写入简化为顺序写的 Log,并通过将计算与存储分离,把复杂的数据持久化、一致性、数据合并都扔给一个高可用的共享存储系统来完成,进而打开写入的天花板,将昂贵的写入容量提升一个量级;

 

  • 第二种思路承认分片的必要性,将这种分片的策略集成到一套整体的分布式数据库体系中,同时通过 Paxos/Raft  复制协议加上多实例节点来实现数据强一致的高可用,其中代表产品有 Google 的 Spanner & F1、TiDB(https://github.com/pingcap/tidb)、CockRoachDB(https://github.com/cockroachdb/cockroach) 等,是比较理想的 Sharding + Proxy 的替代方案。


http://chatgpt.dhexx.cn/article/B68fXbuj.shtml

相关文章

分库分表方案

一、为什么要进行分库分表 当MySQL单表数据量过大,比如超过5千万条的时候,读写性能变得很差。而且常规的优化手段已经不起作用了,比如:SQL调优、添加索引、主从复制、读写分离。这时候就需要用到MySQL终极优化方案 — 分库分表。 …

分库分表设计方案

一、为什么要分库分表? 随着业务的不断发展,数据量不断增加,因此数据操作,如增删改查的开销也会越来越大,原来基于单库单表的设计已经不能满足存储需求,数据库随时面临爆库风险; 再加上物理服务器的资源有…

python:numpy的corrcoef计算相关系数

corrcoef(x, yNone, rowvarTrue, biasnp._NoValue, ddofnp._NoValue)函数常用的是前三个参数,x和y分别是需要计算相关系数的两个随机变量,当rowvar为True(默认情况)时,每一行代表一个随机变量,否则每一列代表一个随机变量。 该函数…

python 计算相关性系数np.corrcoef()

计算相关性是分析连续型与连续型双变量的常用方法,散点图只能直观的显示双变量(特征)之间的关系,但并不能说明关系的强弱,而相关性可以对变量之间的关系进行量化分析。 相关性系数的公式如下: 相关性系数…

Numpy库 numpy.corrcoef()函数

相关系数公式: 其他详见: 1. Python Numpy库 numpy.corrcoef()函数讲解 2. 协方差、方差、标准差、协方差系数 3. 标准差、方差、协方差三者的表示意义

MATLAB中的corrcoef函数求两个向量的相关系数。

 想用MATLAB中的corrcoef函数求两个向量的相关系数。 比如A[1 2 3];B[5 3 7]; r corrcoef(A,B)可以求出相关系数是0.5.为什么两个向量的元素都要是3个以上才行?而只有两个元素的向量如A[1 2];B[5 3];不管怎么随机的取,相关系数都…

使用numpy计算相关系数矩阵:np.corrcoef()

【小白从小学Python、C、Java】 【Python-计算机等级考试二级】 【Python-数据分析】 使用numpy计算相关系数矩阵 np.corrcoef() 选择题 关于以下代码说法错误的是? import numpy as np array1np.array([[1,2,3], [2,3,4], [2,3,3], [4,3,2], [4,3,3]]) print(array1) print(&…

matlab 计算相关系数,MATLAB如何使用corrcoef函数计算样本数据的相关系数

MATLAB如何使用corrcoef函数计算样本数据的相关系数 【语法说明】 Rcorrcoef(X):如果X为向量,函数返回1;如果X为mn 矩阵,则以每行为观测值,每列为一个随机变量计算相关系数,返回一个nn对称矩阵。假设协方差…

numpy.corrcoef()函数讲解

numpy.corrcoef(x, y无, rowvar True, 偏差<无值>, ddof<无值>) 【学习参考】&#xff1a;Python Numpy库 numpy.corrcoef()函数讲解_Hello_xzy_Word的博客-CSDN博客_numpy.corrcoef x&#xff1a; array_like&#xff0c;包含多个变量和观测值的1-D或2-D数组&a…

Python Numpy库 numpy.corrcoef()函数讲解

例子&#xff1a; 代码&#xff1a; import numpy as npArray1 [[1, 2, 3], [4, 5, 6]] Array2 [[11, 25, 346], [734, 48, 49]] Mat1 np.array(Array1) Mat2 np.array(Array2) correlation np.corrcoef(Mat1, Mat2) print("矩阵1\n", Mat1) print("矩阵…

一、求相关函数 corrcoef+协方差矩阵cov

1. 求相关函数corrcoef 一般作用&#xff1a;1&#xff09;结合图表评估数据拟合效果&#xff1b;2&#xff09;评估两组数据之间的互相关联程度&#xff0c;大于0正相关&#xff0c;小于0负相关&#xff0c;等于0不相关。 但此种计算方法反映的是“线性相关”程度&#xff0…

MATLAB 协方差 [cov] 和相关系数 [corrcoef] 说明

A,B为两个长度相同的向量 求协方差 Scov(A,B); b和c数值上是相等的。 求相关系数 Rcorrcoef(A,B) 数值上,f和g是相同到。 相关系数存在许多种类&#xff0c;上述corrcoef 指 pearson correlation coefficient。 性质&#xff1a;向量乘常数&#xff0c;不改变Pearson 相关…

皮尔逊相关分析的MATLAB实现,corr(),corrcoef()函数使用

皮尔逊相关系数可以用来表述两个序列的相关性。 常常用来做数据分析、数据挖掘等工作。 如何简单快捷的实现皮尔逊相关&#xff0c;并得到结果&#xff1f; 需要应用MATLAB中的corr(X, Y)或者 corrcoef(X,Y)函数。 其中corr(X, Y)既可以计算矩阵相关也可以计算序列相关&…

用C语言实现简单的计算器

功能介绍 用C语言实现整形简单的加减乘除操作&#xff08;通常方法与使用函数指针数组的方法&#xff09; 代码实现 方法一 #define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h> #include<stdlib.h>int main() {while (1){double x 0, y 0, ret 0;//定义运…

C语言编写一个计算器(附全源代码)

这个计算器其实是我老师布置的一个c语言大作业,捉摸着搞了那么久的东西不能浪费了吧,于是我分享下我的代码和大概思路 给个关注点个赞,后续我会分享更多我们学生党的作业问题 白嫖党们先看代码,我就先上上全代码,干! 前言: 为了达到目的,首先自学了栈:按照先进后出的…

抗量子加密:为什么你迫切需要它

作者 | John 翻译| Katie&#xff0c;责编 | 晋兆雨 出品 | AI科技大本营 头图 | 付费下载于视觉中国 第二次世界大战把间谍活动带到了最前线&#xff0c;这是网络安全的先兆&#xff0c;正如现代世界所看到的那样。诸如量子计算机之类的技术进步使我们必须将这场打击网络犯罪的…

量子计算机的加密安全性,公钥加密机制被量子计算机攻破,传统加密方式不再安全...

如今市场上不乏各种加密和解密方案,然而,根据研究人员表示,针对那些仅取决于质因子分解难度的方案已经逐渐不适用了。 根据美国麻省理工学院(MIT)研究学者与奥地利因斯布鲁克大学(University of Innsbruck)原型专家表示,目前所使用的“公钥” (public-key)加密方式最终将被…

10年老台式机4分钟攻破量子加密算法,此前12年无人破解,核心原理来自25年前...

明敏 发自 凹非寺量子位 | 公众号 QbitAI 只花4分钟&#xff0c;就破解了量子加密算法的密钥。 用的还是一台有10年“高龄”的台式机。 完全破解也只需62分钟&#xff0c;CPU单核即可搞定。 两位鲁汶大学学者基于数学理论破解量子加密算法的消息&#xff0c;最近轰动了密码学界…

应用量子数据加密的一些问题

前言 最近有看到一本关于量子科技的书籍&#xff0c;里面对量子计算在信息安全领域的应用提出了以下几个问题&#xff0c;我把它们搬运到CSDN&#xff0c;欢迎大家前来讨论&#xff01; 应用量子数据加密的一些问题 1、人类可以利用量子物理学来创造出绝对安全的通信网络吗&…

量子计算会摧毁区块链和加密货币吗?

2019年&#xff0c;谷歌高调宣布了成功演示“量子霸权”&#xff0c;一个包含53个有效量子比特的处理器“西克莫”&#xff0c;用200秒完成传统超级计算机Summit需1万年解决的问题&#xff0c;着实让人惊叹。可是&#xff0c;“量子霸权”还没有捂热&#xff0c;竞争对手IBM就出…