企业项目管理、ORK、研发管理与敏捷开发工具平台

网站首页 > 精选文章 正文

mysql分表分库方案全解析——好的分表分库方案怎么炼成的?

wudianyun 2025-01-13 18:27:45 精选文章 36 ℃

Mysql常用分表分库方案

1、分表的触发条件(什么情况下需要分表)

单表数据量超500W行或数据量大于2G,此时mysql性能下降,就需要考虑分表。(来自阿里开发公约)

  • 判断是否分表,不能脱离单表数据量大小,仅关注表中的数据行数是不可取的。

2、分区、分表、分库如何选择?

类型

触发条件/应用场景

分区

1、当单个表的数据量增大,且响应时间变长时,首先考虑的不是分表,而是分区。2、对于需要按时间段或按某种业务逻辑划分的数据集,考虑分区管理(如:按年份区分订单数据场景)

分表

当单表数据量过大,超500W行或数据量大于2G,此时考虑分表。

分库

通常在,数据库QPS过高,数据库连接数不足时,考虑分库。

分区、分表、分库的顺序按逻辑来说一般为:优先考虑分区,再考虑分表、最后考虑分库。即先后顺序可以理解为分区——分表——分库。

注:分区存在:分区键设计不够灵活、DDL操作面临锁定的风险、可能引发数据倾斜等一系列问题,故实际架构中,分表与分库比分区更受欢迎

3、分表——水平拆分(横向拆分)

按照相同的列,依据一定的策略(如:hash、range),横向对数据库的行进行拆分,将一个表中的行拆分到多个表当中。水平拆分表满足两个定律:1、拆分后每个表的结构都一样;2、每个表的行数据都不一样

常见的水平分表策略

1、range策略

通常意义上的range策略是按照某个字段的范围进行切分,例如我们通常会按照用户ID的范围来拆分表(遵循左闭右开的原则);range也可以进行延展,例如年、月、日范围或地理位置等。

2、基于哈希切分

根据哈希值将数据拆分到不同的表或数据库。(注:哈希切分不完全等同于数值取模拆分,数值取模拆分只是一种特定的哈希方法)Hash分库分表是最普遍的方案。

3、基于目录切分

创建并维护一个路由表或目录,基于路由表或目录的映射关系将数据拆分到不同的表。

4、分表——垂直拆分(纵向拆分)

垂直分表简单来说是将单个表按照列的不同特性进行拆分,将一个表中的列拆分到多个表中。垂直分表满足两个定律:-1、每个表的结构(列)都不一样;-2、每个表的数据几乎都不一样,还是存在有交集的列,一般是用于关联的主键。

垂直分表通常按照业务模块的不同进行划分,也可以数据的访问模式进行划分(即将热点数据与冷数据分开存储)

5、分库——垂直拆分

垂直分库的核心是以表为依据,按照业务属性或业务归属的不同,将不同的表拆分到不同的库中。垂直分库遵循两个定律:-1、分开后,每个库的结构都不相同(表不同);-2、每个库的数据也没有交集(数据不同)

6、分库——水平拆分

垂直分库的核心是以表为依据,按照业务属性或业务归属的不同,将不同的表拆分到不同的库中。垂直分库遵循两个定律:-1、分开后,每个库的结构都不相同(表不同);-2、每个库的数据也没有交集(数据不同)

在垂直分库的基础上,ERP数据库分为四个库后,还存在QPS问题,这个时候可以将库进行水平拆分,如下图所示:

如果上面的水平分库逻辑不好理解,可以理解为数据库进行水平切割(在表上切了一刀),原来一个表中的数据将会分配到不同的数据库中。如下图所示:

7、分表分库——常用工具

工具名称

支持分表

支持分库

支持的数据类型

支持的存储引擎

特性

ShardingSphere

支持多种数据类型

InnoDB, MyISAM等

支持SQL解析、分片、读写分离、弹性伸缩等。

Vitess

主要支持数值和字符串类型

主要支持InnoDB

由YouTube开发的,支持水平扩展、分布式事务等。

MyCAT

支持多种数据类型

支持多种存储引擎

支持SQL路由、读写分离、多种分片策略等。

Cobar

主要支持数值和字符串类型

主要支持InnoDB

阿里巴巴开源,支持SQL解析、分片、读写分离等。

Atlas

支持多种数据类型

主要支持InnoDB

由Qihoo 360开源,主要支持MySQL的分表和读写分离。

ProxySQL

支持多种数据类型

支持多种存储引擎

支持查询缓存、负载均衡、读写分离、高可用性等。

MaxScale

支持多种数据类型

支持多种存储引擎

支持缓存、连接池、读写分离、高可用性等。

8、如何评价一个分表分库方案

一个好的分表分库方案需要满足两方面的特性:1、能够规避数据偏斜问题;2、方案可平滑扩容,即方案具有持续性,使用常规扩容方法(翻倍扩容法、一致性Hash扩容法、Snowflake分片)可以实现平滑扩容)

注:数据偏斜问题简单来说就是分表分库不合理,单体数据库中,部分表的数据较多,而其他表中的数据较少,业务上的表现就是高并发时出现延迟波动的情况。

简易的分表分库(基于时间戳)伪代码核心部分实现如下

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
public class ShardingExample {
public static void main(String[] args) {
DataDAO dataDAO = new DataDAO();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMM");
// 获取当前日期的数据库名和表名
String dbName = dateFormat.format(new Date());
String tableName = "data_" + dbName;
// 插入数据
dataDAO.insertData(tableName, "Sample data for " + dbName);
// 查询数据
List<String> dataList = dataDAO.fetchData(tableName);
for (String data : dataList) {
System.out.println(data);
}
}
}

Tags:

最近发表
标签列表