Sharding-JDBC分库分表入门

ShardingSphere是一套开源的分布式数据库中间件解决方案组成的生态圈, 它由Sharding-JDBC、Sharding-Proxy和Sharding-Sidecar(计划中)这3款相互独立的产品组成.

ShardingSphere定位为关系型数据库中间件, 旨在充分合理地在分布式的场景下利用关系型数据库的计算和存储能力, 而并非实现一个全新的关系型数据库. 它与NoSQL和NewSQL是并存而非互斥的关系.

1. 简介

在对数据库进行读写分离或者分库分表拆分之后, 因为数据库在不同的实例中, 大量的查询压力会分担到不同的机器上. 此时程序需要进行数据库读写时, 需要引入数据库分库分表中间件. 分库分表中间件大致来讲分为两大类: 应用层依赖类中间件、中间层代理类中间件

应用层依赖类中间件特点就是和应用强耦合, 需要应用显示依赖相应的jar包(以Java为例), 比如Sharding-JDBC. 此类的中间件的基本思想就是重新实现JDBC的API, 通过重新实现DataSource、PrepareStatement等操作数据库的接口, 让应用层在基本(注意:这里用了基本)不改变业务代码的情况下透明地实现分库分表的能力. 中间件给上层应用提供熟悉的JDBC API, 内部通过sql解析、sql重写、sql路由等一系列的准备工作获取真正可执行的sql, 然后底层再按照传统的方法(比如数据库连接池)获取物理连接来执行sql, 最后把数据结果合并处理成ResultSet返回给应用层.

中间层代理类中间件: 这类分库分表中间件的核心原理是在应用和数据库的连接之间搭起一个代理层, 上层应用以标准的MySQL协议来连接代理层, 然后代理层负责转发请求到底层的MySQL物理实例, 比如Sharding-Proxy、MyCat, 这种方式对应用只有一个要求, 就是只要用MySQL协议来通信即可, 所以用MySQL Workbench这种纯的客户端都可以直接连接你的分布式数据库, 自然也天然支持所有的编程语言.

本文讲解的ShardingSphere一共分为三部分, 其中Sharding-Sidecar还在开发中. 更多信息查看shardingsphere文档

Sharding-Sidecar: 定位为Kubernetes的云原生数据库代理, 以Sidecar的形式代理所有对数据库的访问. 通过无中心、零侵入的方案提供与数据库交互的的啮合层, 即Database Mesh, 又可称数据网格.

Sharding-Proxy: 定位为透明化的数据库代理端, 提供封装了数据库二进制协议的服务端版本, 用于完成对异构语言的支持. 目前先提供MySQL/PostgreSQL版本, 它可以使用任何兼容MySQL/PostgreSQL协议的访问客户端(如:MySQL Command Client, MySQL Workbench, Navicat等)操作数据, 对DBA更加友好.

Sharding-JDBC: 定位为轻量级Java框架, 在Java的JDBC层提供的额外服务. 它使用客户端直连数据库, 以jar包形式提供服务, 无需额外部署和依赖, 可理解为增强版的JDBC驱动, 完全兼容JDBC和各种ORM框架. 也是本文的重点

2. 读写分离

首先创建两个MySQL实例, 并创建数据库、表, 配置MySQL主从复制, 具体可以查看博客中的MySQL主从复制. 配置完成后, 开始编写代码.

DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user`  (
  `user_id` bigint(20) NOT NULL,
  `username` varchar(255) NULL DEFAULT NULL,
  `password` varchar(255) NULL DEFAULT NULL,
  PRIMARY KEY (`user_id`) USING BTREE
) ENGINE = InnoDB;

首先创建一个SpringBoot项目, 添加如下依赖.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
    <version>4.0.0-RC1</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.47</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

之后就是创建启动类、Dao类以及测试类. 代码比较简单, 暂时省略, 就是使用jpa对user表进行简单查询.

# application.properties文件
spring.profiles.active=master-slave

spring.jpa.database=mysql
spring.jpa.show-sql=false
spring.jpa.hibernate.ddl-auto=none

spring.shardingsphere.props.sql.show=true

# applicatio-master-slave.properties
# 读写分离
spring.shardingsphere.datasource.names=master,slave1

spring.shardingsphere.datasource.master.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.master.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.master.jdbc-url=jdbc:mysql://192.168.88.35:3306/sharding?useUnicode=true&autoReconnect=true&characterEncoding=UTF-8&useSSL=false
spring.shardingsphere.datasource.master.username=root
spring.shardingsphere.datasource.master.password=root

spring.shardingsphere.datasource.slave1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.slave1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.slave1.jdbc-url=jdbc:mysql://192.168.88.36:3306/sharding?useUnicode=true&autoReconnect=true&characterEncoding=UTF-8&useSSL=false
spring.shardingsphere.datasource.slave1.username=root
spring.shardingsphere.datasource.slave1.password=root

spring.shardingsphere.masterslave.load-balance-algorithm-type=round_robin
spring.shardingsphere.masterslave.name=master
spring.shardingsphere.masterslave.master-data-source-name=master
spring.shardingsphere.masterslave.slave-data-source-names=slave1

此处配置了两个MySQL实例, IP35为主数据库, IP36为从数据库. 运行测试类, 两个数据库中的数据都能正常返回.

3. 数据库分表

创建一个MySQL实例, 创建多个表, 表名格式为t_user_${index}, 此处的index最好是2的N次方. 代码依旧使用读写分离时的代码, 额外添加一个配置文件.

# application-sharding-tables.properties
spring.shardingsphere.datasource.names=ds
spring.shardingsphere.datasource.ds.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds.jdbc-url=jdbc:mysql://192.168.88.88:3306/sharding?useUnicode=true&autoReconnect=true&characterEncoding=UTF-8&useSSL=false
spring.shardingsphere.datasource.ds.username=root
spring.shardingsphere.datasource.ds.password=root

# 实际表名 -> 格式为数据库名.表名
spring.shardingsphere.sharding.tables.t_invoice.actual-data-nodes=ds.t_user_$->{0..15}
# 分表字段 -> 按照哪个字段分
spring.shardingsphere.sharding.tables.t_invoice.table-strategy.inline.sharding-column=user_id
# 分表策略表达式 -> 按照manager_id取模获得表名
spring.shardingsphere.sharding.tables.t_invoice.table-strategy.inline.algorithm-expression=t_user_$->{user_id % 15}
# 自增列名称
spring.shardingsphere.sharding.tables.t_invoice.key-generator.column=invoice_id
spring.shardingsphere.sharding.tables.t_invoice.key-generator.type=SNOWFLAKE
spring.shardingsphere.sharding.tables.t_invoice.key-generator.props.worker.id=5

此处配置了一个数据库和16张t_user表, 修改application.properties文件中spring.profiles.active=msharding-tables, 运行测试类, 16张表数据都能正常返回.

posted on 2021-02-18 14:12  annwyn  阅读(143)  评论(0)    收藏  举报

导航