分库分表怎么配?
Posted ConstXiong
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分库分表怎么配?相关的知识,希望对你有一定的参考价值。
之前研究了 mysql 通过主从复制的方式,使用 Sharding-JDBC 实现读写分离。
分库分表的实现方案
代码怎么写?怎么配?
create table t_order0(
order_id int primary key,
user_id int,
goods_id int,
goods_name varchar(200)
);
create table t_order1(
order_id int primary key,
user_id int,
goods_id int,
goods_name varchar(200)
);
<!-- 当前最新版 sharding-jdbc -->
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-core</artifactId>
<version>4.1.1</version>
</dependency>
<!-- 结合官方文档使用了 HikariCP 数据库连接池 -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>3.4.5</version>
</dependency>
<!-- MySQL 8.0.21 驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
1package constxiong;
2
3import com.zaxxer.hikari.HikariDataSource;
4
5/**
6 * 获取 DataSource 工具类,使用了 Hikari 数据库连接池
7 */
8import javax.sql.DataSource;
9
10public final class DataSourceUtil {
11
12 private static final int PORT = 3306;
13
14 /**
15 * 通过 Hikari 数据库连接池创建 DataSource
16 * @param ip
17 * @param username
18 * @param password
19 * @param dataSourceName
20 * @return
21 */
22 public static DataSource createDataSource(String ip, String username, String password, String dataSourceName) {
23 HikariDataSource result = new HikariDataSource();
24 result.setDriverClassName(com.mysql.jdbc.Driver.class.getName());
25 result.setJdbcUrl(String.format("jdbc:mysql://%s:%s/%s?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8", ip, PORT, dataSourceName));
26 result.setUsername(username);
27 result.setPassword(password);
28 return result;
29 }
30}
测试逻辑:
使用数据源工具类,新建 ds0 和 ds1 库的数据源
配置 t_order 表的规则,ds$->{0..1}.t_order$->{0..1}
配置分库分表的规则,分库根据 ds 拼接上 t_order 的 user_id 字段值 对 2 取模的值(ds${user_id % 2});分表根据 t_order 拼接上 order_id 字段值 对 2 取模的值(t_order${order_id % 2})
测试 insert 不同的 user_id 和 order_id 是否会按规则插入不同的库和表
查询 user_id = 2 的数据,看看是否正常查出
1package constxiong;
2
3import org.apache.shardingsphere.api.config.sharding.ShardingRuleConfiguration;
4import org.apache.shardingsphere.api.config.sharding.TableRuleConfiguration;
5import org.apache.shardingsphere.api.config.sharding.strategy.InlineShardingStrategyConfiguration;
6import org.apache.shardingsphere.shardingjdbc.api.ShardingDataSourceFactory;
7
8import javax.sql.DataSource;
9import java.sql.Connection;
10import java.sql.ResultSet;
11import java.sql.SQLException;
12import java.sql.Statement;
13import java.util.HashMap;
14import java.util.Map;
15import java.util.Properties;
16
17/**
18 * 测试 ShardingSphere 分表分库
19 */
20public class Test {
21
22 //DataSource 0
23 private static DataSource ds0 = DataSourceUtil.createDataSource("172.31.32.234", "root", "constxiong@123", "constxiong");
24 // DataSource 1
25 private static DataSource ds1 = DataSourceUtil.createDataSource("172.31.32.184", "root", "constxiong@123", "constxiong");
26
27 public static void main(String[] args) throws SQLException {
28 // 配置真实数据源
29 Map<String, DataSource> dataSourceMap = new HashMap<>();
30 dataSourceMap.put("ds0", ds0);
31 dataSourceMap.put("ds1", ds1);
32
33 // 配置Order表规则
34 TableRuleConfiguration orderTableRuleConfig = new TableRuleConfiguration("t_order", "ds$->{0..1}.t_order$->{0..1}");
35
36 // 配置分库 + 分表策略
37 orderTableRuleConfig.setDatabaseShardingStrategyConfig(new InlineShardingStrategyConfiguration("user_id", "ds${user_id % 2}"));
38 orderTableRuleConfig.setTableShardingStrategyConfig(new InlineShardingStrategyConfiguration("order_id", "t_order${order_id % 2}"));
39
40 // 配置分片规则
41 ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
42 shardingRuleConfig.getTableRuleConfigs().add(orderTableRuleConfig);
43
44 // 获取数据源对象
45 DataSource dataSource = ShardingDataSourceFactory.createDataSource(dataSourceMap, shardingRuleConfig, new Properties());
46 Connection connection = dataSource.getConnection();
47 Statement statement = connection.createStatement();
48 statement.execute("insert into t_order value(1, 1, 1, '电视机')");
49 statement.execute("insert into t_order value(2, 1, 2, '可乐')");
50 statement.execute("insert into t_order value(3, 2, 8, '空调')");
51 statement.execute("insert into t_order value(4, 2, 9, '手机壳')");
52
53 statement.execute("select * from t_order where user_id = 2");
54 ResultSet resultSet = statement.getResultSet();
55 while (resultSet.next()) {
56 System.out.printf("user_id:%d, order_id:%d, goods_id:%d, goods_name:%s\n",
57 resultSet.getInt("user_id"),
58 resultSet.getInt("order_id"),
59 resultSet.getInt("goods_id"),
60 resultSet.getString("goods_name")
61 );
62 }
63 }
64}
user_id = 2 数据代码查询
user_id:2, order_id:4, goods_id:9, goods_name:手机壳
user_id:2, order_id:3, goods_id:8, goods_name:空调
补充
文中通过 JDBC 方式实现数据库操作,先弄明白了原生,后面再来看 SpringBoot 的配置才能知道哪些类接收处理了参数,底层调用了哪些 API,框架整合的时候出了问题可以快速排查。
Sharding-JDBC 在实现分库分表时,涉及了很多概念,如逻辑表、真实表、数据节点、绑定表、广播表。文中代码里的 insert、select 语句里的 t_order 就是逻辑表,实际插入与查询是在 t_order0 和 t_order1 表。
ds$->{0..1}.t_order$->{0..1},$->{0..1} 表示范围区间,取 0、1,这些配置规则在官方文档中都有说明。
官方文档也列出了 Sharding-JDBC 不支持的功能,如不支持存储过程,函数,游标的操作等。技术选型的时候,不能忽视它的能力范围。
参考
https://shardingsphere.apache.org/document/current/cn/user-manual/shardingsphere-jdbc/usage/sharding/java-api/
https://shardingsphere.apache.org/document/current/cn/features/sharding/
讨论
以上是关于分库分表怎么配?的主要内容,如果未能解决你的问题,请参考以下文章