关于分库分表:分而治之浅谈分库分表及实践之路-京东云技术团队

7次阅读

共计 5592 个字符,预计需要花费 14 分钟才能阅读完成。

前言

之前总在聊微服务,微服务自身也是分布式系统,其实微服务的核心思想是分而治之,把一个简单的单体零碎,依照业务的交付,分成不同的自服务,以升高资深复杂度,同时能够晋升零碎的扩展性。

明天想聊一下分库分表,因为对于快速增长的业务来说,这个是无奈回避的一环。之前我在做商城相干的 SAAS 零碎,商品池是一个存储瓶颈,商品池数量会基于租户增长和经营变得指数级增长,短短几个月就能涨到几千万的数据,而经营半年后就可能过亿。而对于订单这种数据,也会跟着业务的成长,也会变得愈发微小。

存储层来说,晋升大数据量下的存储和查问性能,就波及到了另一个层面的问题,但思维还是一样的,分而治之。

咱们面临什么样的问题

关系型数据库在大于肯定数据量的状况下检索性能会急剧下降。在面对海量数据状况时,所有数据都存于一张表,显然会轻易超过数据库表可接受的。

此外单纯的分表尽管能够解决数据量过大导致检索变慢的问题,但无奈解决过多并发申请拜访同一个库,导致数据库响应变慢的问题。所以须要分库来解决单数据库实例性能瓶颈问题。

数据库架构计划

在讲具体解决方案之前,咱们须要先理解一下数据库的三种架构波及计划。

1. Shared Everything

个别指的是单个主机的环境,齐全通明共享的 CPU/ 内存 / 硬盘,并行处理能力是最差的,个别不思考大规模的并发需要,架构比较简单,个别的利用需要根本都能满足。

2. Shared Disk

各处理单元应用本人的公有 CPU 和 Memory,共享磁盘零碎。典型的代表是 Oracle RAC、DB2 PureScale。例如 Oracle RAC,他用的是共享存储,做到了数据共享,可通过减少节点来进步并行处理的能力,扩大能力较好,应用 Storage Area Network (SAN),光纤通道连贯到多个服务器的磁盘阵列,升高网络耗费,进步数据读取的效率,罕用于并发量较高的 OLTP 利用。其相似于 SMP(对称多解决)模式,然而当存储器接口达到饱和的时候,减少节点并不能取得更高的性能,同时更多的节点,则减少了运维的老本。

3. Shared Nothing

各处理单元都有本人公有的 CPU/ 内存 / 硬盘等,Nothing,顾名思义,不存在共享资源,相似于 MPP(大规模并行处理)模式,各处理单元之间通过协定通信,并行处理和扩大能力更好。典型代表 DB2 DPF、带分库分表的 MySQL Cluster,各节点互相独立,各自解决本人的数据,解决后的后果可能向下层汇总或在节点间流转。

咱们常说的 Sharding 其实就是 Shared Nothing,他是将某个表从物理存储上被程度宰割,并调配给多台服务器(或多个实例),每台服务器能够独立工作,具备独特的 schema,例如 MySQL Proxy 和 Google 的各种架构,只需减少服务器数就能够减少解决能力和容量。

至于 MPP,指的是大规模并行剖析数据库(Analytical Massively Parallel Processing (MPP) Databases),他是针对剖析工作负载进行了优化的数据库,个别须要聚合和解决大型数据集。MPP 数据库往往是列式的,因而 MPP 数据库通常将每一列存储为一个对象,而不是将表中的每一行存储为一个对象。这种体系结构使简单的剖析查问能够更快,更无效地解决。例如 TeraData、Greenplum,GaussDB100、TBase。

基于以上的这几种架构计划,咱们能够给出大数据量存储的解决方案:

[]()

以上几种解决方案各有利弊,分区模式最大的问题是准 share everything 架构,无奈程度扩大 cpu 和内存,所以根本能够排除;nosql 自身其实是个十分好的备选计划,然而 nosql(包含大部分开源 newsql)硬件耗费十分大,运维老本较高。而罕用的一种计划就是基于 Mysql 的分库分表计划。

分库分表架构计划

对于分库分表,首先看一下市面上有哪些产品。

业界组件 原厂 性能个性 备注
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 驱动

对于分库分表的产品模式,又分为两种,中间件模式和客户端模式。

1. 中间件模式其优缺点

中间件模式独立过程,所以能够反对异构语言,对以后程序没有侵入性,对业务方来说是通明的 mysql 服务,然而毛病也非常明显,硬件耗费大、运维老本高(尤其是在本地化施行状况下),同时因为对关系型数据库减少了代理,会造成问题难调试。

2. 客户端模式优缺点

客户端模式的次要毛病是对代码有侵入,所以根本只能反对单语言,同时因为每个客户端都要对 schema 建设连贯,所以如果数据库实例不多,须要对连接数认真管制,然而客户端模式的长处也非常明显,首先从架构上它是去中心化的,这样就防止了中间件模式的 proxy 故障问题,同时因为没有中间层性能高、灵便可控,而且因为没有 proxy 层,不须要思考 proxy 的高可用和集群,运维老本也比拟低。

sharding-jdbc 接入实战

sharding-jdbc 其实是这些产品中最为大家熟知的,也是因为它定位为轻量级 Java 框架,在 Java 的 JDBC 层提供的额定服务。它应用客户端直连数据库,以 jar 包模式提供服务,无需额定部署和依赖,可了解为增强版的 JDBC 驱动,齐全兼容 JDBC 和各种 ORM 框架。实用于任何基于 JDBC 的 ORM 框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template 或间接应用 JDBC。而且在社区活跃度,代码品质等方面,也是很不错的。接下来,我讲具体讲一下接入细节。

1. 组件集成

<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId> <version> 5.0.0</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.4.0</version>
</dependency> 

2. bean 配置

配置 sharding jdbc 数据源并且退出到动静数据源中,用于数据源路由。

[]()

批改原配置核心对应服务的 mysql 数据源配置,对不分库分表的数据源配置为动静数据源默认路由

[]()

3. sharing JDBC 配置

spring.shardingsphere.enabled=true #shardingsphere 开关 
spring.shardingsphere.props.sql.show=true 
spring.shardingsphere.mode.type=Standalone #在应用配置核心的状况下,应用 standalone 模式即可(memery、standalone、cluster 三种模式)spring.shardingsphere.mode.repository.type=File #standalone 模式下应用 File,即以后配置文件 
spring.shardingsphere.mode.overwrite=true # 本地配置是否笼罩配置核心配置。如果可笼罩,每次启动都以本地配置为准。spring.shardingsphere.datasource.names=ds-0,ds-1 #配置数据源名字,实在数据源 
#配置 ds- 0 数据源 
spring.shardingsphere.datasource.ds-0.jdbc-url=jdbc:mysql://**** 
spring.shardingsphere.datasource.ds-0.type=com.zaxxer.hikari.HikariDataSource 
spring.shardingsphere.datasource.ds-0.driver-class-name=com.mysql.jdbc.Driver 
spring.shardingsphere.datasource.ds-0.username= 
spring.shardingsphere.datasource.ds-0.password= 
#配置 ds- 1 数据源 
spring.shardingsphere.datasource.ds-1.jdbc-url=jdbc:mysql://****
spring.shardingsphere.datasource.ds-1.type=com.zaxxer.hikari.HikariDataSource 
spring.shardingsphere.datasource.ds-1.driver-class-name=com.mysql.jdbc.Driver 
spring.shardingsphere.datasource.ds-1.username= 
spring.shardingsphere.datasource.ds-1.password= 
#配置模式数据库分片键和相干的表 
spring.shardingsphere.rules.sharding.default-database-strategy.standard.sharding-column=user_id 
spring.shardingsphere.rules.sharding.default-database-strategy.standard.sharding-algorithm-name=database-inline 
spring.shardingsphere.rules.sharding.binding-tables[0]=t_order,t_order_item 
spring.shardingsphere.rules.sharding.broadcast-tables=t_address #配置播送表,即所有库中都会同步增删的表 

以上是一些根本配置,还有一些业务场景配置,大家能够参考开源社区文档: https://shardingsphere.apache.org/document/4.1.0/cn/overview/

总结

对于具体业务场景,咱们首先是基于 DDD 的思维划分业务单元,最开始先做好垂直分库。接着是针对一些特定的业务增长量微小的表,进行程度的分库解决,比方商品子域中的商品池表,订单子域中的订单表等等。

而在分表维度,业务初期,就要最好垂直分表的设计。比方商品池设计中,只须要存储关系信息,而商品详情的信息独自存储在一个底表之中。

作者:京东物流 赵勇萍

起源:京东云开发者社区

正文完
 0