参考:https://blog.csdn.net/u013982921/article/details/94006668
Sharding-JDBC,Sharding-Proxy,Sharding-Sidecar 数据库任意MySQLMySQL连接消耗数高低高异构语言仅Java任意任意性能损耗低损耗略高损耗低无中心化是否是静态入口无有无
| Sharding-JDBC | Sharding-Proxy | Sharding-Sidecar | |
|---|---|---|---|
| 数据库 | 任意 | MYSQL | MYSQL |
| 连接消耗数 | 高 | 低 | 高 |
| 异构语言 | 仅Java | 任意 | 任意 |
| 性能 | 损耗低 | 损耗略高 | 损耗低 |
| 无中心化 | 是 | 否 | 是 |
| 静态入口 | 无 | 有 | 否 |
分库分表:mycat,sharding-sphere
2. 创建数据库和表
ds0
├── user_0
└── user_1
ds1
├── user_0
└── user_1
既然是分库分表 库结构与表结构一定是一致的
数据库: ds0
CREATE DATABASE IF NOT EXISTS `ds0` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci */;
USE `ds0`; SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for user_0 --
----------------------------
DROP TABLE IF EXISTS `user_0`;
CREATE TABLE `user_0` ( `id` int(11) NOT NULL, `name` varchar(255) DEFAULT NULL, `age` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- ----------------------------
-- Table structure for user_1 --
----------------------------
DROP TABLE IF EXISTS `user_1`;
CREATE TABLE `user_1` ( `id` int(11) NOT NULL, `name` varchar(255) DEFAULT NULL, `age` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
SET FOREIGN_KEY_CHECKS = 1;
数据库: ds1
CREATE DATABASE IF NOT EXISTS `ds1` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci */;
USE `ds1`; SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for user_0 --
----------------------------
DROP TABLE IF EXISTS `user_0`;
CREATE TABLE `user_0` ( `id` int(11) NOT NULL, `name` varchar(255) DEFAULT NULL, `age` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- ----------------------------
-- Table structure for user_1 --
----------------------------
DROP TABLE IF EXISTS `user_1`;
CREATE TABLE `user_1` ( `id` int(11) NOT NULL, `name` varchar(255) DEFAULT NULL, `age` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
SET FOREIGN_KEY_CHECKS = 1;
3. application.properties (重点)基本是在这个文件配置的
# 数据源 ds0,ds1
sharding.jdbc.datasource.names=ds0,ds1
# 第一个数据库
sharding.jdbc.datasource.ds0.type=com.zaxxer.hikari.HikariDataSource
sharding.jdbc.datasource.ds0.driver-class-name=com.mysql.cj.jdbc.Driver
sharding.jdbc.datasource.ds0.jdbc-url=jdbc:mysql://localhost:3306/ds0?characterEncoding=utf-8&&serverTimezone=GMT%2B8
sharding.jdbc.datasource.ds0.username=root
sharding.jdbc.datasource.ds0.password=root
# 第二个数据库
sharding.jdbc.datasource.ds1.type=com.zaxxer.hikari.HikariDataSource
sharding.jdbc.datasource.ds1.driver-class-name=com.mysql.cj.jdbc.Driver
sharding.jdbc.datasource.ds1.jdbc-url=jdbc:mysql://localhost:3306/ds1?characterEncoding=utf-8&&serverTimezone=GMT%2B8
sharding.jdbc.datasource.ds1.username=root
sharding.jdbc.datasource.ds1.password=root
# 水平拆分的数据库(表) 配置分库 + 分表策略 行表达式分片策略
# 分库策略
sharding.jdbc.config.sharding.default-database-strategy.inline.sharding-column=id
sharding.jdbc.config.sharding.default-database-strategy.inline.algorithm-expression=ds$->{id % 2}
# 分表策略 其中user为逻辑表 分表主要取决于age行
sharding.jdbc.config.sharding.tables.user.actual-data-nodes=ds$->{0..1}.user_$->{0..1}
sharding.jdbc.config.sharding.tables.user.table-strategy.inline.sharding-column=age
# 分片算法表达式
sharding.jdbc.config.sharding.tables.user.table-strategy.inline.algorithm-expression=user_$->{age % 2}
# 主键 UUID 18位数 如果是分布式还要进行一个设置 防止主键重复
#sharding.jdbc.config.sharding.tables.user.key-generator-column-name=id
# 打印执行的数据库以及语句
sharding.jdbc.config.props..sql.show=true
spring.main.allow-bean-definition-overriding=true
我这次使用配置文件方式实现分库以及分表
以上配置说明:
逻辑表 user
水平拆分的数据库(表)的相同逻辑和数据结构表的总称。例:用户数据根据主键尾数拆分为2张表,分别是user0到user1,他们的逻辑表名为user。
真实表
在分片的数据库中真实存在的物理表。即上个示例中的user0到user1
分片算法:
Hint分片算法
对应HintShardingAlgorithm,用于处理使用Hint行分片的场景。需要配合HintShardingStrategy使用。
分片策略:
行表达式分片策略 对应InlineShardingStrategy。使用Groovy的表达式,提供对SQL语句中的=和IN的分片操作支持,只支持单分片键。对于简单的分片算法,可以通过简单的配置使用,从而避免繁琐的Java代码开发,如: user$->{id % 2} 表示user表根据id模2,而分成2张表,表名称为user0到user_1。
自增主键生成策略
通过在客户端生成自增主键替换以数据库原生自增主键的方式,做到分布式主键无重复。 采用UUID.randomUUID()的方式产生分布式主键。或者 SNOWFLAKE
4. 实体类
-
package com.zhang.shardingtable.entity; -
import com.baomidou.mybatisplus.annotation.TableName; -
import com.baomidou.mybatisplus.extension.activerecord.Model; -
import groovy.transform.EqualsAndHashCode; -
import lombok.Data; -
import lombok.experimental.Accessors; -
/** -
* @Classname User -
* @Description 用户实体类 -
* @Author 章国文 13120739083@163.com -
* @Date 2019-06-28 17:24 -
* @Version 1.0 -
*/ -
@Data -
@EqualsAndHashCode(callSuper = true) -
@Accessors(chain = true) -
@TableName("user") -
public class User extends Model<User> { -
/** -
* 主键Id -
*/ -
private int id; -
/** -
* 名称 -
*/ -
private String name; -
/** -
* 年龄 -
*/ -
private int age; -
}
5. dao层
-
package com.zhang.shardingtable.mapper; -
import com.baomidou.mybatisplus.core.mapper.BaseMapper; -
import com.zhang.shardingtable.entity.User; -
/** -
* user dao层 -
* @author lihaodong -
*/ -
public interface UserMapper extends BaseMapper<User> { -
}
6. service层以及实现类
UserService
-
package com.zhang.shardingtable.service; -
import com.baomidou.mybatisplus.extension.service.IService; -
import com.zhang.shardingtable.entity.User; -
import java.util.List; -
/** -
* @Classname UserService -
* @Description 用户服务类 -
* @Author 章国文 13120739083@163.com -
* @Date 2019-06-28 17:31 -
* @Version 1.0 -
*/ -
public interface UserService extends IService<User> { -
/** -
* 保存用户信息 -
* @param entity -
* @return -
*/ -
@Override -
boolean save(User entity); -
/** -
* 查询全部用户信息 -
* @return -
*/ -
List<User> getUserList(); -
}
UserServiceImpl
-
package com.zhang.shardingtable.service.Impl; -
import com.baomidou.mybatisplus.core.toolkit.Wrappers; -
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -
import com.zhang.shardingtable.entity.User; -
import com.zhang.shardingtable.mapper.UserMapper; -
import com.zhang.shardingtable.service.UserService; -
import org.springframework.stereotype.Service; -
import java.util.List; -
/** -
* @Classname UserServiceImpl -
* @Description 用户服务实现类 -
* @Author 章国文 13120739083@163.com -
* @Date 2019-06-28 17:32 -
* @Version 1.0 -
*/ -
@Service -
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService { -
@Override -
public boolean save(User entity) { -
return super.save(entity); -
} -
@Override -
public List<User> getUserList() { -
return baseMapper.selectList(Wrappers.<User>lambdaQuery()); -
} -
}
7. 控制类
-
package com.zhang.shardingtable.controller; -
import com.zhang.shardingtable.entity.User; -
import com.zhang.shardingtable.service.UserService; -
import org.springframework.beans.factory.annotation.Autowired; -
import org.springframework.web.bind.annotation.GetMapping; -
import org.springframework.web.bind.annotation.RestController; -
import java.util.List; -
/** -
* @Classname UserController -
* @Description 用户测试控制类 -
* @Author 章国文 13120739083@163.com -
* @Date 2019-06-28 17:36 -
* @Version 1.0 -
*/ -
@RestController -
public class UserController { -
@Autowired -
private UserService userService; -
@GetMapping("/select") -
public List<User> select() { -
return userService.getUserList(); -
} -
@GetMapping("/insert") -
public Boolean insert(User user) { -
return userService.save(user); -
} -
}
四. 测试
启动项目
打开浏览器 分别访问:
http://localhost:8080/insert?id=1&name=lhd&age=12
http://localhost:8080/insert?id=2&name=lhd&age=13
http://localhost:8080/insert?id=3&name=lhd&age=14
http://localhost:8080/insert?id=4&name=lhd&age=15
可以在控制台看到如下展示,表示插入成功了
根据分片算法和分片策略 不同的id以及age取模落入不同的库表 达到了分库分表的结果
有的人说 查询的话 该怎么做呢 其实也帮我们做好了 打开浏览器 访问:
http://localhost:8080/select
分别从ds0数据库两张表和ds1两张表查询结果 然后汇总结果返回
之前有朋友问我单表数据量达千万,想做水平分割,不分库,也可以的吧?
是完全可以的 只要修改配置文件的配置即可 非常灵活
1万+

被折叠的 条评论
为什么被折叠?



