項目初期沒有強大的 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