项目初期没有强大的 DBA, 随着用户增长, 订单表愈来愈大, MySQL 的主机负载一直下不来, 致使吞吐下降html
表结构:java
CREATE TABLE `order_0` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`order_id` bigint(20) unsigned NOT NULL,
`uid` bigint(20) unsigned NOT NULL,
`money` int(11) NOT NULL,
`status` tinyint(3) unsigned NOT NULL DEFAULT '0',
`create_time` datetime NOT NULL,
`modified_time` datetime NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_order_id` (`order_id`),
KEY `idx_uid` (`uid`)
) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8mb4
复制代码
因为是单
key
业务, 只须要经过uid
来查询, 则按照uid
来作分表因子node
通过一些权衡, 仍是准备使用 shardingsphere ,社区活跃度也比较不错mysql
jdk 8 , shardingsphere 版本 4.0.0-RC2git
uid | uid % 2 (库) | uid / 2 % 4 (表) |
---|---|---|
1 | 1 | 0 |
2 | 0 | 1 |
3 | 1 | 1 |
4 | 0 | 2 |
5 | 1 | 2 |
6 | 0 | 3 |
7 | 1 | 3 |
8 | 0 | 0 |
CREATE TABLE `order_0` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`order_id` bigint(20) unsigned NOT NULL,
`uid` bigint(20) unsigned NOT NULL,
`money` int(11) NOT NULL,
`status` tinyint(3) unsigned NOT NULL DEFAULT '0',
`create_time` datetime NOT NULL,
`modified_time` datetime NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_order_id` (`order_id`),
KEY `idx_uid` (`uid`)
) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8mb4
CREATE TABLE `order_1` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`order_id` bigint(20) unsigned NOT NULL,
`uid` bigint(20) unsigned NOT NULL,
`money` int(11) NOT NULL,
`status` tinyint(3) unsigned NOT NULL DEFAULT '0',
`create_time` datetime NOT NULL,
`modified_time` datetime NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_order_id` (`order_id`),
KEY `idx_uid` (`uid`)
) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8mb4
CREATE TABLE `order_2` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`order_id` bigint(20) unsigned NOT NULL,
`uid` bigint(20) unsigned NOT NULL,
`money` int(11) NOT NULL,
`status` tinyint(3) unsigned NOT NULL DEFAULT '0',
`create_time` datetime NOT NULL,
`modified_time` datetime NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_order_id` (`order_id`),
KEY `idx_uid` (`uid`)
) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8mb4
CREATE TABLE `order_3` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`order_id` bigint(20) unsigned NOT NULL,
`uid` bigint(20) unsigned NOT NULL,
`money` int(11) NOT NULL,
`status` tinyint(3) unsigned NOT NULL DEFAULT '0',
`create_time` datetime NOT NULL,
`modified_time` datetime NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_order_id` (`order_id`),
KEY `idx_uid` (`uid`)
) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8mb4
复制代码
<!--web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--自动生成 GET SET-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--链接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.12</version>
</dependency>
<!--MySQL-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--mybatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>4.0.0-RC2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
复制代码
spring.shardingsphere.datasource.names=db0,db1
spring.shardingsphere.datasource.db0.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.db0.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.db0.url=jdbc:mysql://localhost:3306/db0?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=convertToNull
spring.shardingsphere.datasource.db0.username=root
spring.shardingsphere.datasource.db0.password=root
spring.shardingsphere.datasource.db1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.db1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.db1.url=jdbc:mysql://localhost:3306/db1?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=convertToNull
spring.shardingsphere.datasource.db1.username=root
spring.shardingsphere.datasource.db1.password=root
# 是否显示SQL语句
spring.shardingsphere.props.sql.show=true
# 配置数据库和表
spring.shardingsphere.sharding.tables.order.actual-data-nodes=db$->{0..1}.order_$->{0..1}
# 配置根据哪一个字段选择数据库
spring.shardingsphere.sharding.tables.order.database-strategy.inline.sharding-column=uid
# 配置选择哪一个数据库的规则
spring.shardingsphere.sharding.tables.order.database-strategy.inline.algorithm-expression=db$->{uid % 2}
# 配置选择根据哪一个字段选择表
spring.shardingsphere.sharding.tables.order.table-strategy.inline.sharding-column=uid
# 配置选择哪一个表的规则
spring.shardingsphere.sharding.tables.order.table-strategy.inline.algorithm-expression=order_$->{(Integer)(uid / 2) % 4}
复制代码
须要注意, 查询订单详情须要带上用户 uid, 用来路由到对应的库和表github
大众点评订单系统分库分表实践spring
若是不当之处, 欢迎指出, 共同成长sql