数据库分库分表

何时分库分表

数据库性能出现问题后,一般按照如下步骤优化:
① 参数优化 ② 缓存、索引 ③ 读写分离 ④ 分库分表 (最终方案)

  1. 分库
  • 服务器磁盘空间不足、内存不足、 CPU 压力过大,导致读写性能瓶颈。
  • 网络带宽不足,响应慢,导致客户端连接等待/超时。
  • 数据量过大,影响读写性能;MySQL单库数据量在5000万以内性能比较好,超过阈值后性能会随着数据量的增大而变弱。MySQL单表的数据量是500w-1000w之间性能比较好,超过1000w性能也会下降。
  • 数据库连接数过多,响应慢,导致客户端连接等待/超时。MySQL数据库默认100个连接,单机最大1500连接。
  1. 分表
  • 单表出现性能瓶颈,通常是因为单表数据量过大,导致读写性能较慢。一般B+树索引高度是2~3层最佳,如果数据量千万级别,可能高度就变4层了,数据读写就会明显变慢。

分库分表方式

可以分为两种垂直切分和水平切分模式

  • 垂直切分
    垂直分库,按照业务模块进行切分,将不同模块的表切分到不同的数据库中。垂直分库把一个库的压力分摊到多个库,提升了一些数据库性能,但并没有解决由于单表数据量过大导致的性能问题,所以就需要配合后边的分表来解决。
    垂直分表,将表中不同的字段切分到同意数据库不同的表中。一般是把业务宽表中比较独立的字段,或者不常用的字段拆分到单独的数据表中,是一种大表拆小表的模式。
  • 水平切分
    水平分库是把同一个表按一定规则拆分到不同的数据库中,每个库可以位于不同的服务器上,以此实现水平扩展。
    水平分表是在同一个数据库中将一张大表按照一定的切分规则,按照行切分成不同的表。

水平分表(策略)

主流的切分策略有:Range 范围、hash切分、range+hash取模混合、映射表

  • Range 范围
    是指按某个字段的数据区间来进行切分。比如,表按照 id 的数据范围切分成多张表,每 1000万条数据存放一张表,切分后的表可以放到同一个数据库,也可以放到不同的数据库。
    优点: 有利于扩容,后续扩容不需要数据迁移。
    缺点: 存在写偏移,会有热点问题。比如,按照时间来划分时,最近的数据会聚集在一张表中,所以读写流量全部集中在最新的表。
  • hash切分
    通过对分表键 key 进行一定的运算(通常有取余、取模运算),通过运算结果来决定路由的库和表。
    优点: 数据分片比较均匀,大大降低热点问题。
    缺点: 后期扩容可能需要迁移数据。
  • range+hash取模混合
    拆分库的时候,可以先用range范围方案,再用hash取模的策略把同一range库中的表进行切分。
  • 映射表
    将分表键和数据库的映射关系记录在一个单独的表(表的形式可以是数据库表、文件或者配置中心)。
    优点: 可以灵活设置路由规则。
    缺点: 映射表可能也会随着业务量的增大,同样需要分库分表。

分库分表后的问题

  • 分布式ID问题
    分库分表后,需要维护全局唯一的ID,常用的算法有:UUID、数据库自增生成全局ID、利用Redis的incr命令生成主键、雪花算法。
  • 分布式事务问题
    分库分表之后可能就需要引入分布式事务的问题,解决方案有两种:
    1. 业务划分的时候规避分布式事务;
    2. 使用专业的的分布式框架,比如阿里开源的 Seata;
  • 跨库关联问题
    1. 将有E-R关系的表存储到一个库中。
    2. 对于数据量少的表建成全局表,分布到各个库中
    3. 对于必须跨库join的,最多支持跨两张表的跨库join。跨节点Join的问题:解决这一问题可以分两次查询实现
  • 分页问题
    分页问题,解决方案有三种:
    1. 选择合适的分表字段,规避绝大部分高频查询场景出现跨库;
    2. 使用专业的分布式框架,比如开源框架:ElasticSearch;
    3. 业务代码中分别查询,然后组装数据;
  • 排序问题
    跨节点的count,order by,group by以及聚合函数等问题:可以分别在各个节点上得到结果后在应用程序端进行合并。
  • 增加调试和维护难度

分库分表中间件

分库分表工具主要有 2种模式:客户端模式 和 代理模式。客户端模式是指在客户端实现直连数据库,客户端通常是通过一些封装好的 jar来实现,常见的开源中间件有:Apache的Sharding-JDBC、淘宝的TDDL、美图的Zebra。代理模式是指需要单独部署服务,客户端连接代理服务,由代理服务再和数据库交互,常见的开源中间件有:Apache的 Sharding-Proxy、阿里的 cobar、国产的 MyCat、360的 Atlas。另外还有 google的 vitess,它是基于 zookeeper,通过 RPC方式进行数据管理。

业界组件 原厂 功能特性 备注
DBLE 爱可生开源社区 专注于 mysql 的高可扩展性的分布式中间件 基于 MyCAT 开发出来的增强版。
Meituan Atlas 美团 读写分离、单库分表 目前已经在原厂逐步下架。
Cobar 阿里(B2B) Cobar 中间件以 Proxy 的形式位于前台应用和实际数据库之间,对前台的开放的接口是 MySQL 通信协议 开源版本中数据库只支持 MySQL,并且不支持读写分离。
MyCAT 阿里 是一个实现了 MySQL 协议的服务器,前端用户可以把它看作是一个数据库代理,用 MySQL 客户端工具和命令行访问,而其后端可以用 MySQL 原生协议与多个 MySQL 服务器通信 MyCAT 基于阿里开源的 Cobar 产品而研发
Atlas 360 读写分离、静态分表 2015 年后已经不在维护
Kingshard 开源项目 由 Go 开发高性能 MySQL Proxy 项目,在满足基本的读写分离的功能上,Kingshard 的性能是直连 MySQL 性能的 80% 以上。
TDDL 阿里淘宝 动态数据源、读写分离、分库分表 TDDL 分为两个版本,一个是带中间件的版本,一个是直接 Java 版本
Zebra 美团点评 实现动态数据源、读写分离、分库分表、CAT 监控 功能齐全且有监控,接入复杂、限制多。
MTDDL 美团点评 动态数据源、读写分离、分布式唯一主键生成器、分库分表、连接池及 SQL 监控
Vitess 谷歌、Youtube 集群基于 ZooKeeper 管理,通过 RPC 方式进行数据处理,总体分为,server,command line,gui 监控 3 部分 Youtube 大量应用
DRDS 阿里 DRDS(Distributed Relational Database Service)专注于解决单机关系型数据库扩展性问题,具备轻量 (无状态)、灵活、稳定、高效等特性,是阿里巴巴集团自主研
Sharding-proxy apache 开源项目 提供 MySQL 版本,它可以使用任何兼容 MySQL 协议的访问客户端 (如:MySQL Command Client, MySQL Workbench 等) 操作数据,对 DBA 更加友好。向应用程序完全透明,可直接当做 MySQL 使用。适用于任何兼容 MySQL 协议的客户端。 Apache 项目,定位为透明化的数据库代理端,提供封装了数据库二进制协议的服务端版本,用于完成对异构语言的支持。
Sharding jdbc apache 开源项目 完全兼容 JDBC 和各种 ORM 框架。适用于任何基于 Java 的 ORM 框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template 或直接使用 JDBC。基于任何第三方的数据库连接池,如:DBCP,C3P0, BoneCP, Druid, HikariCP 等。支持任意实现 JDBC 规范的数据库。目前支持 MySQL,Oracle,SQLServer 和 PostgreSQL Apache 项目,定位为轻量级 Java 框架,在 Java 的 JDBC 层提供的额外服务。 它使用客户端直连数据库,以 jar 包形式提供服务,无需额外部署和依赖,可理解为增强版的 JDBC 驱动

参考:

什么时候需要分表分库,怎么做分表分库?

数据库分库分表思路

posted @ 2024-01-16 14:27  永不停转  阅读(183)  评论(0编辑  收藏  举报