Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
KnowledgePlanet
road-map
xfg-dev-tech-shardingjdbc
提交
e470682b
xfg-dev-tech-shardingjdbc
项目概览
KnowledgePlanet
/
road-map
/
xfg-dev-tech-shardingjdbc
通知
126
Star
17
Fork
9
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
xfg-dev-tech-shardingjdbc
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
e470682b
编写于
11月 03, 2023
作者:
小傅哥
⛹
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
小傅哥,feat:shardingjdbc 案例
上级
变更
16
显示空白变更内容
内联
并排
Showing
16 changed file
with
1005 addition
and
0 deletion
+1005
-0
README.md
README.md
+224
-0
pom.xml
pom.xml
+127
-0
xfg-dev-tech-app/pom.xml
xfg-dev-tech-app/pom.xml
+132
-0
xfg-dev-tech-app/src/main/java/cn/bugstack/xfg/dev/tech/Application.java
...p/src/main/java/cn/bugstack/xfg/dev/tech/Application.java
+15
-0
xfg-dev-tech-app/src/main/resources/application-dev.yml
xfg-dev-tech-app/src/main/resources/application-dev.yml
+18
-0
xfg-dev-tech-app/src/main/resources/application-prod.yml
xfg-dev-tech-app/src/main/resources/application-prod.yml
+18
-0
xfg-dev-tech-app/src/main/resources/application-test.yml
xfg-dev-tech-app/src/main/resources/application-test.yml
+18
-0
xfg-dev-tech-app/src/main/resources/application.yml
xfg-dev-tech-app/src/main/resources/application.yml
+5
-0
xfg-dev-tech-app/src/main/resources/logback-spring.xml
xfg-dev-tech-app/src/main/resources/logback-spring.xml
+114
-0
xfg-dev-tech-app/src/main/resources/mybatis/config/mybatis-config.xml
...-app/src/main/resources/mybatis/config/mybatis-config.xml
+10
-0
xfg-dev-tech-app/src/main/resources/mybatis/mapper/user_order_mapper.xml
...p/src/main/resources/mybatis/mapper/user_order_mapper.xml
+52
-0
xfg-dev-tech-app/src/main/resources/sharding/sharding-jdbc-dev.yaml
...ch-app/src/main/resources/sharding/sharding-jdbc-dev.yaml
+75
-0
xfg-dev-tech-app/src/test/java/cn/bugstack/xfg/dev/tech/test/ApiTest.java
.../src/test/java/cn/bugstack/xfg/dev/tech/test/ApiTest.java
+76
-0
xfg-dev-tech-infrastructure/pom.xml
xfg-dev-tech-infrastructure/pom.xml
+44
-0
xfg-dev-tech-infrastructure/src/main/java/cn/bugstack/xfg/dev/tech/infrastructure/dao/IUserOrderDao.java
...gstack/xfg/dev/tech/infrastructure/dao/IUserOrderDao.java
+17
-0
xfg-dev-tech-infrastructure/src/main/java/cn/bugstack/xfg/dev/tech/infrastructure/po/UserOrderPO.java
.../bugstack/xfg/dev/tech/infrastructure/po/UserOrderPO.java
+60
-0
未找到文件。
README.md
0 → 100644
浏览文件 @
e470682b
# sharding-jdbc
本文的宗旨在于通过简单干净实践的方式教会读者,快速 Easy 的使用上 sharding-jdbc 这个笨重的大家伙!
之所以说笨重,是因为
[
Apache ShardingSphere
](
https://shardingsphere.apache.org/index_zh.html
)
不只是简单意义上的路由组件,而是一款分布式 SQL 事务和查询引擎,可通过数据分片、弹性伸缩、加密等能力对任意数据库进行增强。同时它又在迭代过程中,衍生出了很多的版本,以及对应了不同的使用方式。并在 ShardingSphere 5.3 以后又做了不小的架构调整。所以很多伙伴在使用的时候,经常是找了一上午的资料,到下午下班还没对接上。
本文涉及的工程:
-
xfg-dev-tech-shardingjdbc:
[
https://gitcode.net/KnowledgePlanet/road-map/xfg-dev-tech-shardingjdbc
](
https://gitcode.net/KnowledgePlanet/road-map/xfg-dev-tech-shardingjdbc
)
-
官网:
[
https://shardingsphere.apache.org/index_zh.html
](
https://shardingsphere.apache.org/index_zh.html
)
## 一、路由本质
分库分表的本质是数据的散列,分摊数据库资源压力。如把原本在一台机器上的数据库存放1000万数据,分摊到n台机上,拆分这1000万的数据和后续的增量。让每个数据库资源来分摊原本需要一台数据库所提供的服务。
<div
align=
"center"
>
<img
src=
"./docs/images/roadmap-shardingjdbc-01.png?raw=true"
width=
"600px"
>
</div>
-
当使用分库分表以后,并确定如使用
`用户ID`
作为路由分片键。那么所做的CRUD操作,都是需要使用到这个用户ID,并根据ID做路由库表计算。
-
在大厂中,开发项目。并不会说目前这个业务需求规模不大,就不使用分库分表,而是分库分表都是非常成熟的方案,并不会因为使用了就降低很大的开发效率。所以基本就是默认就使用了。
-
那么使用了分库分表,就会很占用资源吗。也不会,因为刚开始业务体量不大的时候,都是虚拟机交叉使用,你的1台物理机虚出来10个虚拟机,大家交叉使用主备。这样你只是使用了分库分表,但库表的实际资源没占用那么多。
## 二、使用案例
-
jdk 1.8 +
-
ShardingSphere 5.3+
```
pom
<!-- https://mvnrepository.com/artifact/org.apache.shardingsphere/shardingsphere-jdbc-core -->
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc-core</artifactId>
<version>5.4.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.yaml/snakeyaml -->
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.33</version>
</dependency>
```
-
因为需要解析 yaml 但默认的 SpringBoot 提供版本不支持 shardingsphere-jdbc-core 使用。
### 1. 工程结构
<div
align=
"center"
>
<img
src=
"./docs/images/roadmap-shardingjdbc-02.png?raw=true"
width=
"850px"
>
</div>
-
工程中,提供了 docker 配置数据库环境操作,并提供了对应的建表测试语句。如果你本机已经安装了数据库,那么只做库表语句导入以及 yml 配置数据库连接信息就可以。
-
sharding-jdbc-dev.yaml 配置了详细的分库分表路由信息,在 algorithms 下配置的是库表的路由算法。这里的算法要根据实际自己使用中库表数量来设置&设计,避免发生较大的数据偏移。
-
配置完 sharding-jdbc-dev.yaml 需要在 application-dev.yml 中配置上 sharding-jdbc-dev.yaml 路径,这样才能正确加载。
-
如果你还需要定义出自己特定的路由算法,它还支持自己写个实现类的方式处理。
### 2. 算法配置
**sharding/sharding-jdbc-dev.yaml**
```
yml
# https://shardingsphere.apache.org/index_zh.html
mode
:
# 运行模式类型。可选配置:内存模式 Memory、单机模式 Standalone、集群模式 Cluster - 目前为单机模式
type
:
Standalone
dataSources
:
ds_0
:
dataSourceClassName
:
com.zaxxer.hikari.HikariDataSource
driverClassName
:
com.mysql.cj.jdbc.Driver
jdbcUrl
:
jdbc:mysql://127.0.0.1:13306/xfg_dev_tech_db_00?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&serverTimezone=UTC&useSSL=true
username
:
root
password
:
123456
connectionTimeoutMilliseconds
:
30000
idleTimeoutMilliseconds
:
60000
maxLifetimeMilliseconds
:
1800000
maxPoolSize
:
15
minPoolSize
:
5
ds_1
:
dataSourceClassName
:
com.zaxxer.hikari.HikariDataSource
driverClassName
:
com.mysql.cj.jdbc.Driver
jdbcUrl
:
jdbc:mysql://127.0.0.1:13306/xfg_dev_tech_db_01?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&serverTimezone=UTC&useSSL=true
username
:
root
password
:
123456
connectionTimeoutMilliseconds
:
30000
idleTimeoutMilliseconds
:
60000
maxLifetimeMilliseconds
:
1800000
maxPoolSize
:
15
minPoolSize
:
5
rules
:
-
!SHARDING
# 库的路由
defaultDatabaseStrategy
:
standard
:
shardingColumn
:
user_id
shardingAlgorithmName
:
database_inline
# 表的路由
tables
:
user_order
:
actualDataNodes
:
ds_$->{0..1}.user_order_$->{0..3}
tableStrategy
:
standard
:
shardingColumn
:
user_id
shardingAlgorithmName
:
user_order_inline
# 路由算法
shardingAlgorithms
:
# 库-路由算法 2是两个库,库的数量。库的数量用哈希模2来计算。
database_inline
:
type
:
INLINE
props
:
algorithm-expression
:
ds_$->{Math.abs(user_id.hashCode()) % 2}
# 表-路由算法 4是一个库里,表的数量。4 - 1 为了获得 011 这样的二进制值。不推荐 user_order_$->{Math.abs(user_id.hashCode()) % 2} 作为表的路由
user_order_inline
:
type
:
INLINE
props
:
algorithm-expression
:
user_order_$->{(user_id.hashCode() ^ (user_id.hashCode()) >>> 16) & (4 - 1)}
props
:
# 是否在日志中打印 SQL。
# 打印 SQL 可以帮助开发者快速定位系统问题。日志内容包含:逻辑 SQL,真实 SQL 和 SQL 解析结果。
# 如果开启配置,日志将使用 Topic ShardingSphere-SQL,日志级别是 INFO。 false
sql-show
:
true
# 是否在日志中打印简单风格的 SQL。false
sql-simple
:
true
# 用于设置任务处理线程池的大小。每个 ShardingSphereDataSource 使用一个独立的线程池,同一个 JVM 的不同数据源不共享线程池。
executor-size
:
20
# 查询请求在每个数据库实例中所能使用的最大连接数。1
max-connections-size-per-query
:
1
# 在程序启动和更新时,是否检查分片元数据的结构一致性。
check-table-metadata-enabled
:
false
# 在程序启动和更新时,是否检查重复表。false
check-duplicate-table-enabled
:
false
```
-
mode:运行模式,默认就单机模式。
-
dataSources:数据库连接信息。
-
rules:路由算法。defaultDatabaseStrategy 库的路由、tables 表的路由。之后在 shardingAlgorithms 中配置具体的路由算法。这里的名称都是关联的,不要配置错。
-
props:一些属性信息,包括是否打印日志等。
### 3. 配置引入
**application-dev.yml**
```
yml
spring
:
datasource
:
driver-class-name
:
org.apache.shardingsphere.driver.ShardingSphereDriver
url
:
jdbc:shardingsphere:classpath:sharding/sharding-jdbc-dev.yaml
```
-
和之前的一些 sharding 版本不同,这里是需要使用具体的 ShardingSphereDriver 和 url 地址,才能加载上我们配置的路由信息。
## 三、测试验证
<div
align=
"center"
>
<img
src=
"./docs/images/roadmap-shardingjdbc-03.png?raw=true"
width=
"850px"
>
</div>
-
基于工程中 docs/dev-ops/mysql/sql 创建库表。已经提供了库名、表和测试数据。
-
无论你使用哪种方式,都可以安装MySql 并使用可视化工具链接。这里小傅哥用的是
[
Sequel Ace
](
https://apps.apple.com/us/app/sequel-ace/id1518036000?ls=1
)
### 1. 写入数据
```
java
@Test
public
void
test_insert
()
{
for
(
int
i
=
0
;
i
<
1000
;
i
++)
{
UserOrderPO
userOrderPO
=
UserOrderPO
.
builder
()
.
userName
(
"小傅哥"
)
.
userId
(
"xfg_"
+
RandomStringUtils
.
randomAlphabetic
(
6
))
.
userMobile
(
"+86 13521408***"
)
.
sku
(
"13811216"
)
.
skuName
(
"《手写MyBatis:渐进式源码实践》"
)
.
orderId
(
RandomStringUtils
.
randomNumeric
(
11
))
.
quantity
(
1
)
.
unitPrice
(
BigDecimal
.
valueOf
(
128
))
.
discountAmount
(
BigDecimal
.
valueOf
(
50
))
.
tax
(
BigDecimal
.
ZERO
)
.
totalAmount
(
BigDecimal
.
valueOf
(
78
))
.
orderDate
(
new
Date
())
.
orderStatus
(
0
)
.
isDelete
(
0
)
.
uuid
(
UUID
.
randomUUID
().
toString
().
replace
(
"-"
,
""
))
.
ipv4
(
"127.0.0.1"
)
.
ipv6
(
"2001:0db8:85a3:0000:0000:8a2e:0370:7334"
.
getBytes
())
.
extData
(
"{\"device\": {\"machine\": \"IPhone 14 Pro\", \"location\": \"shanghai\"}}"
)
.
build
();
userOrderDao
.
insert
(
userOrderPO
);
}
}
```
-
测试数据写入,你可以写入1000条数据,观察散列效果。并可以在这个过程中,调试修改 sharding-jdbc-dev.yaml 文件对库表路由的计算方式。
### 2. 查询数据
```
java
@Test
public
void
test_selectByUserId
()
{
List
<
UserOrderPO
>
list
=
userOrderDao
.
selectByUserId
(
"xfg_PrmgwQ"
);
log
.
info
(
"测试结果:{}"
,
JSON
.
toJSONString
(
list
));
}
```
-
查询的用户ID是已经写入到数据库表里的数据,查询的时候会根据用户ID继续路由计算。
### 3. 散列算法
```
java
@Test
public
void
test_idx
()
{
for
(
int
i
=
0
;
i
<
50
;
i
++)
{
String
user_id
=
"xfg_"
+
RandomStringUtils
.
randomAlphabetic
(
6
);
log
.
info
(
"测试结果 {}"
,
(
user_id
.
hashCode
()
^
(
user_id
.
hashCode
())
>>>
16
)
&
3
);
}
}
```
-
你可以尝试验证和编写新的散列算法,最终目的都是让数据尽可能散列到库表。
-
此外,关于算法的好坏,可以基于
[
雪崩测试
](
https://bugstack.cn/md/algorithm/logic/math/2022-11-05-fibonacci.html
)
计算
pom.xml
0 → 100644
浏览文件 @
e470682b
<?xml version="1.0" encoding="UTF-8"?>
<project
xmlns=
"http://maven.apache.org/POM/4.0.0"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
>
<modelVersion>
4.0.0
</modelVersion>
<groupId>
cn.bugstack
</groupId>
<artifactId>
xfg-dev-tech-shardingjdbc
</artifactId>
<version>
1.0-SNAPSHOT
</version>
<packaging>
pom
</packaging>
<modules>
<module>
xfg-dev-tech-app
</module>
<module>
xfg-dev-tech-infrastructure
</module>
</modules>
<properties>
<java.version>
1.8
</java.version>
<project.build.sourceEncoding>
UTF-8
</project.build.sourceEncoding>
<maven.compiler.source>
8
</maven.compiler.source>
<maven.compiler.target>
8
</maven.compiler.target>
<project.build.sourceEncoding>
UTF-8
</project.build.sourceEncoding>
</properties>
<parent>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-parent
</artifactId>
<version>
2.7.12
</version>
<relativePath/>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>
org.mybatis.spring.boot
</groupId>
<artifactId>
mybatis-spring-boot-starter
</artifactId>
<version>
2.1.4
</version>
</dependency>
<!-- # 多数据源路由配置
# mysql 5.x driver-class-name: com.mysql.jdbc.Driver mysql-connector-java 5.1.34
# mysql 8.x driver-class-name: com.mysql.cj.jdbc.Driver mysql-connector-java 8.0.22-->
<dependency>
<groupId>
mysql
</groupId>
<artifactId>
mysql-connector-java
</artifactId>
<version>
8.0.22
</version>
</dependency>
<dependency>
<groupId>
com.alibaba
</groupId>
<artifactId>
fastjson
</artifactId>
<version>
2.0.28
</version>
</dependency>
<dependency>
<groupId>
org.apache.commons
</groupId>
<artifactId>
commons-lang3
</artifactId>
<version>
3.9
</version>
</dependency>
<!-- Aug 04, 2021 https://mvnrepository.com/artifact/org.apache.commons/commons-dbcp2 application-dbcp.yml -->
<dependency>
<groupId>
org.apache.commons
</groupId>
<artifactId>
commons-dbcp2
</artifactId>
<version>
2.9.0
</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.shardingsphere/shardingsphere-jdbc-core -->
<dependency>
<groupId>
org.apache.shardingsphere
</groupId>
<artifactId>
shardingsphere-jdbc-core
</artifactId>
<version>
5.4.1
</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<finalName>
xfg-dev-tech
</finalName>
<plugins>
<plugin>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-compiler-plugin
</artifactId>
<version>
3.0
</version>
<configuration>
<source>
${java.version}
</source>
<target>
${java.version}
</target>
<encoding>
${project.build.sourceEncoding}
</encoding>
</configuration>
</plugin>
<plugin>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-resources-plugin
</artifactId>
<version>
2.5
</version>
<configuration>
<encoding>
UTF-8
</encoding>
</configuration>
</plugin>
<!-- 统一设定POM版本信息插件 -->
<plugin>
<groupId>
org.codehaus.mojo
</groupId>
<artifactId>
versions-maven-plugin
</artifactId>
<version>
2.7
</version>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>
dev
</id>
<activation>
<activeByDefault>
true
</activeByDefault>
</activation>
<properties>
<profileActive>
dev
</profileActive>
</properties>
</profile>
<profile>
<id>
test
</id>
<properties>
<profileActive>
test
</profileActive>
</properties>
</profile>
<profile>
<id>
prod
</id>
<properties>
<profileActive>
prod
</profileActive>
</properties>
</profile>
</profiles>
</project>
\ No newline at end of file
xfg-dev-tech-app/pom.xml
0 → 100644
浏览文件 @
e470682b
<?xml version="1.0" encoding="UTF-8"?>
<project
xmlns=
"http://maven.apache.org/POM/4.0.0"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
>
<modelVersion>
4.0.0
</modelVersion>
<parent>
<groupId>
cn.bugstack
</groupId>
<artifactId>
xfg-dev-tech-shardingjdbc
</artifactId>
<version>
1.0-SNAPSHOT
</version>
</parent>
<artifactId>
xfg-dev-tech-app
</artifactId>
<dependencies>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-web
</artifactId>
<exclusions>
<exclusion>
<artifactId>
snakeyaml
</artifactId>
<groupId>
org.yaml
</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-configuration-processor
</artifactId>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-test
</artifactId>
<scope>
test
</scope>
</dependency>
<dependency>
<groupId>
org.mybatis.spring.boot
</groupId>
<artifactId>
mybatis-spring-boot-starter
</artifactId>
</dependency>
<!-- # 多数据源路由配置
# mysql 5.x driver-class-name: com.mysql.jdbc.Driver mysql-connector-java 5.1.34
# mysql 8.x driver-class-name: com.mysql.cj.jdbc.Driver mysql-connector-java 8.0.22-->
<dependency>
<groupId>
mysql
</groupId>
<artifactId>
mysql-connector-java
</artifactId>
</dependency>
<dependency>
<groupId>
org.apache.shardingsphere
</groupId>
<artifactId>
shardingsphere-jdbc-core
</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.yaml/snakeyaml -->
<dependency>
<groupId>
org.yaml
</groupId>
<artifactId>
snakeyaml
</artifactId>
<version>
1.33
</version>
</dependency>
<dependency>
<groupId>
com.alibaba
</groupId>
<artifactId>
fastjson
</artifactId>
</dependency>
<dependency>
<groupId>
org.apache.commons
</groupId>
<artifactId>
commons-lang3
</artifactId>
</dependency>
<dependency>
<groupId>
org.projectlombok
</groupId>
<artifactId>
lombok
</artifactId>
</dependency>
<dependency>
<groupId>
junit
</groupId>
<artifactId>
junit
</artifactId>
<scope>
test
</scope>
</dependency>
<dependency>
<groupId>
commons-beanutils
</groupId>
<artifactId>
commons-beanutils
</artifactId>
<version>
1.9.4
</version>
</dependency>
<!-- 自身模块 begin -->
<dependency>
<groupId>
cn.bugstack
</groupId>
<artifactId>
xfg-dev-tech-infrastructure
</artifactId>
<version>
1.0-SNAPSHOT
</version>
</dependency>
<!-- 自身模块 end -->
</dependencies>
<build>
<finalName>
xfg-dev-tech-app
</finalName>
<resources>
<resource>
<directory>
src/main/resources
</directory>
<filtering>
true
</filtering>
<includes>
<include>
**/**
</include>
</includes>
</resource>
</resources>
<testResources>
<testResource>
<directory>
src/test/resources
</directory>
<filtering>
true
</filtering>
<includes>
<include>
**/**
</include>
</includes>
</testResource>
</testResources>
<plugins>
<plugin>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-surefire-plugin
</artifactId>
<version>
2.6
</version>
<configuration>
<skipTests>
true
</skipTests>
<testFailureIgnore>
false
</testFailureIgnore>
<includes>
<include>
**/*Test.java
</include>
</includes>
</configuration>
</plugin>
<plugin>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-maven-plugin
</artifactId>
<configuration>
<mainClass>
cn.bugstack.xfg.frame.Application
</mainClass>
<layout>
JAR
</layout>
</configuration>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
xfg-dev-tech-app/src/main/java/cn/bugstack/xfg/dev/tech/Application.java
0 → 100644
浏览文件 @
e470682b
package
cn.bugstack.xfg.dev.tech
;
import
org.springframework.beans.factory.annotation.Configurable
;
import
org.springframework.boot.SpringApplication
;
import
org.springframework.boot.autoconfigure.SpringBootApplication
;
@SpringBootApplication
@Configurable
public
class
Application
{
public
static
void
main
(
String
[]
args
){
SpringApplication
.
run
(
Application
.
class
);
}
}
xfg-dev-tech-app/src/main/resources/application-dev.yml
0 → 100644
浏览文件 @
e470682b
server
:
port
:
8090
spring
:
datasource
:
driver-class-name
:
org.apache.shardingsphere.driver.ShardingSphereDriver
url
:
jdbc:shardingsphere:classpath:sharding/sharding-jdbc-dev.yaml
mybatis
:
mapper-locations
:
classpath:/mybatis/mapper/*.xml
config-location
:
classpath:/mybatis/config/mybatis-config.xml
# 日志
logging
:
level
:
root
:
info
config
:
classpath:logback-spring.xml
\ No newline at end of file
xfg-dev-tech-app/src/main/resources/application-prod.yml
0 → 100644
浏览文件 @
e470682b
server
:
port
:
8090
spring
:
datasource
:
driver-class-name
:
org.apache.shardingsphere.driver.ShardingSphereDriver
url
:
jdbc:shardingsphere:classpath:sharding/sharding-jdbc-dev.yaml
mybatis
:
mapper-locations
:
classpath:/mybatis/mapper/*.xml
config-location
:
classpath:/mybatis/config/mybatis-config.xml
# 日志
logging
:
level
:
root
:
info
config
:
classpath:logback-spring.xml
\ No newline at end of file
xfg-dev-tech-app/src/main/resources/application-test.yml
0 → 100644
浏览文件 @
e470682b
server
:
port
:
8090
spring
:
datasource
:
driver-class-name
:
org.apache.shardingsphere.driver.ShardingSphereDriver
url
:
jdbc:shardingsphere:classpath:sharding/sharding-jdbc-dev.yaml
mybatis
:
mapper-locations
:
classpath:/mybatis/mapper/*.xml
config-location
:
classpath:/mybatis/config/mybatis-config.xml
# 日志
logging
:
level
:
root
:
info
config
:
classpath:logback-spring.xml
\ No newline at end of file
xfg-dev-tech-app/src/main/resources/application.yml
0 → 100644
浏览文件 @
e470682b
spring
:
config
:
name
:
xfg-dev-tech-mybatis
profiles
:
active
:
dev
xfg-dev-tech-app/src/main/resources/logback-spring.xml
0 → 100644
浏览文件 @
e470682b
<?xml version="1.0" encoding="UTF-8"?>
<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 -->
<configuration
scan=
"true"
scanPeriod=
"10 seconds"
>
<contextName>
logback
</contextName>
<!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。 -->
<springProperty
scope=
"context"
name=
"log.path"
source=
"logging.path"
/>
<!-- 日志格式 -->
<conversionRule
conversionWord=
"clr"
converterClass=
"org.springframework.boot.logging.logback.ColorConverter"
/>
<conversionRule
conversionWord=
"wex"
converterClass=
"org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"
/>
<conversionRule
conversionWord=
"wEx"
converterClass=
"org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"
/>
<!-- 输出到控制台 -->
<appender
name=
"CONSOLE"
class=
"ch.qos.logback.core.ConsoleAppender"
>
<!-- 此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息 -->
<filter
class=
"ch.qos.logback.classic.filter.ThresholdFilter"
>
<level>
info
</level>
</filter>
<encoder>
<pattern>
%d{yy-MM-dd.HH:mm:ss.SSS} [%-16t] %-5p %-22c{0}%X{ServiceId} -%X{trace-id} %m%n
</pattern>
<charset>
UTF-8
</charset>
</encoder>
</appender>
<!--输出到文件-->
<!-- 时间滚动输出 level为 INFO 日志 -->
<appender
name=
"INFO_FILE"
class=
"ch.qos.logback.core.rolling.RollingFileAppender"
>
<!-- 正在记录的日志文件的路径及文件名 -->
<file>
./data/log/log_info.log
</file>
<!--日志文件输出格式-->
<encoder>
<pattern>
%d{yy-MM-dd.HH:mm:ss.SSS} [%-16t] %-5p %-22c{0}%X{ServiceId} -%X{trace-id} %m%n
</pattern>
<charset>
UTF-8
</charset>
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy
class=
"ch.qos.logback.core.rolling.TimeBasedRollingPolicy"
>
<!-- 每天日志归档路径以及格式 -->
<fileNamePattern>
./data/log/log-info-%d{yyyy-MM-dd}.%i.log
</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class=
"ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"
>
<maxFileSize>
100MB
</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>
15
</maxHistory>
<totalSizeCap>
10GB
</totalSizeCap>
</rollingPolicy>
</appender>
<!-- 时间滚动输出 level为 ERROR 日志 -->
<appender
name=
"ERROR_FILE"
class=
"ch.qos.logback.core.rolling.RollingFileAppender"
>
<!-- 正在记录的日志文件的路径及文件名 -->
<file>
./data/log/log_error.log
</file>
<!--日志文件输出格式-->
<encoder>
<pattern>
%d{yy-MM-dd.HH:mm:ss.SSS} [%-16t] %-5p %-22c{0}%X{ServiceId} -%X{trace-id} %m%n
</pattern>
<charset>
UTF-8
</charset>
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy
class=
"ch.qos.logback.core.rolling.TimeBasedRollingPolicy"
>
<fileNamePattern>
./data/log/log-error-%d{yyyy-MM-dd}.%i.log
</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class=
"ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"
>
<maxFileSize>
100MB
</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!-- 日志文件保留天数【根据服务器预留,可自行调整】 -->
<maxHistory>
7
</maxHistory>
<totalSizeCap>
5GB
</totalSizeCap>
</rollingPolicy>
<!-- WARN 级别及以上 -->
<filter
class=
"ch.qos.logback.classic.filter.ThresholdFilter"
>
<level>
WARN
</level>
</filter>
</appender>
<!-- 异步输出 -->
<appender
name=
"ASYNC_FILE_INFO"
class=
"ch.qos.logback.classic.AsyncAppender"
>
<!-- 队列剩余容量小于discardingThreshold,则会丢弃TRACT、DEBUG、INFO级别的日志;默认值-1,为queueSize的20%;0不丢失日志 -->
<discardingThreshold>
0
</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
<queueSize>
8192
</queueSize>
<!-- neverBlock:true 会丢失日志,但业务性能不受影响 -->
<neverBlock>
true
</neverBlock>
<!--是否提取调用者数据-->
<includeCallerData>
false
</includeCallerData>
<appender-ref
ref=
"INFO_FILE"
/>
</appender>
<appender
name=
"ASYNC_FILE_ERROR"
class=
"ch.qos.logback.classic.AsyncAppender"
>
<!-- 队列剩余容量小于discardingThreshold,则会丢弃TRACT、DEBUG、INFO级别的日志;默认值-1,为queueSize的20%;0不丢失日志 -->
<discardingThreshold>
0
</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
<queueSize>
1024
</queueSize>
<!-- neverBlock:true 会丢失日志,但业务性能不受影响 -->
<neverBlock>
true
</neverBlock>
<!--是否提取调用者数据-->
<includeCallerData>
false
</includeCallerData>
<appender-ref
ref=
"ERROR_FILE"
/>
</appender>
<!-- 开发环境:控制台打印 -->
<springProfile
name=
"dev"
>
<logger
name=
"com.nmys.view"
level=
"debug"
/>
</springProfile>
<root
level=
"info"
>
<appender-ref
ref=
"CONSOLE"
/>
<!-- 异步日志-INFO -->
<appender-ref
ref=
"ASYNC_FILE_INFO"
/>
<!-- 异步日志-ERROR -->
<appender-ref
ref=
"ASYNC_FILE_ERROR"
/>
</root>
</configuration>
\ No newline at end of file
xfg-dev-tech-app/src/main/resources/mybatis/config/mybatis-config.xml
0 → 100644
浏览文件 @
e470682b
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 暂时未使用 文档:https://mybatis.org/mybatis-3/zh/configuration.html#typeAliases -->
<typeAliases>
</typeAliases>
</configuration>
\ No newline at end of file
xfg-dev-tech-app/src/main/resources/mybatis/mapper/user_order_mapper.xml
0 → 100644
浏览文件 @
e470682b
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper
namespace=
"cn.bugstack.xfg.dev.tech.infrastructure.dao.IUserOrderDao"
>
<resultMap
id=
"dataMap"
type=
"cn.bugstack.xfg.dev.tech.infrastructure.po.UserOrderPO"
>
<id
column=
"id"
property=
"id"
/>
<result
column=
"user_name"
property=
"userName"
/>
<result
column=
"user_id"
property=
"userId"
/>
<result
column=
"user_mobile"
property=
"userMobile"
/>
<result
column=
"sku"
property=
"sku"
/>
<result
column=
"sku_name"
property=
"skuName"
/>
<result
column=
"order_id"
property=
"orderId"
/>
<result
column=
"quantity"
property=
"quantity"
/>
<result
column=
"unit_price"
property=
"unitPrice"
/>
<result
column=
"discount_amount"
property=
"discountAmount"
/>
<result
column=
"tax"
property=
"tax"
/>
<result
column=
"total_amount"
property=
"totalAmount"
/>
<result
column=
"order_date"
property=
"orderDate"
/>
<result
column=
"order_status"
property=
"orderStatus"
/>
<result
column=
"is_delete"
property=
"isDelete"
/>
<result
column=
"uuid"
property=
"uuid"
/>
<result
column=
"ipv4"
property=
"ipv4"
/>
<result
column=
"ipv6"
property=
"ipv6"
/>
<result
column=
"ext_data"
property=
"extData"
/>
<result
column=
"update_time"
property=
"updateTime"
/>
</resultMap>
<select
id=
"insert"
parameterType=
"cn.bugstack.xfg.dev.tech.infrastructure.po.UserOrderPO"
>
INSERT INTO user_order (user_name, user_id, user_mobile, sku, sku_name,
order_id, quantity, unit_price, discount_amount, tax,
total_amount, order_date, order_status, is_delete, uuid,
ipv4, ipv6, ext_data, update_time, create_time)
VALUES (#{userName}, #{userId}, #{userMobile}, #{sku}, #{skuName},
#{orderId}, #{quantity}, #{unitPrice}, #{discountAmount}, #{tax},
#{totalAmount}, #{orderDate}, #{orderStatus}, #{isDelete}, #{uuid},
INET_ATON(#{ipv4}), INET6_ATON(#{ipv6}), #{extData}, now(), now())
</select>
<update
id=
"updateOrderStatusByUserId"
parameterType=
"java.lang.String"
>
UPDATE user_order SET order_status = 1 WHERE user_id = #{userId}
</update>
<select
id=
"selectByUserId"
parameterType=
"java.lang.String"
resultMap=
"dataMap"
>
SELECT id, user_name, user_id, user_mobile, sku, sku_name,
order_id, quantity, unit_price, discount_amount, tax,
total_amount, order_date, order_status, is_delete, uuid,
ipv4, ipv6, ext_data, update_time, create_time
FROM user_order
WHERE user_id = #{userId}
</select>
</mapper>
xfg-dev-tech-app/src/main/resources/sharding/sharding-jdbc-dev.yaml
0 → 100644
浏览文件 @
e470682b
# https://shardingsphere.apache.org/index_zh.html
mode
:
# 运行模式类型。可选配置:内存模式 Memory、单机模式 Standalone、集群模式 Cluster - 目前为单机模式
type
:
Standalone
dataSources
:
ds_0
:
dataSourceClassName
:
com.zaxxer.hikari.HikariDataSource
driverClassName
:
com.mysql.cj.jdbc.Driver
jdbcUrl
:
jdbc:mysql://127.0.0.1:13306/xfg_dev_tech_db_00?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&serverTimezone=UTC&useSSL=true
username
:
root
password
:
123456
connectionTimeoutMilliseconds
:
30000
idleTimeoutMilliseconds
:
60000
maxLifetimeMilliseconds
:
1800000
maxPoolSize
:
15
minPoolSize
:
5
ds_1
:
dataSourceClassName
:
com.zaxxer.hikari.HikariDataSource
driverClassName
:
com.mysql.cj.jdbc.Driver
jdbcUrl
:
jdbc:mysql://127.0.0.1:13306/xfg_dev_tech_db_01?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&serverTimezone=UTC&useSSL=true
username
:
root
password
:
123456
connectionTimeoutMilliseconds
:
30000
idleTimeoutMilliseconds
:
60000
maxLifetimeMilliseconds
:
1800000
maxPoolSize
:
15
minPoolSize
:
5
rules
:
-
!SHARDING
# 库的路由
defaultDatabaseStrategy
:
standard
:
shardingColumn
:
user_id
shardingAlgorithmName
:
database_inline
# 表的路由
tables
:
user_order
:
actualDataNodes
:
ds_$->{0..1}.user_order_$->{0..3}
tableStrategy
:
standard
:
shardingColumn
:
user_id
shardingAlgorithmName
:
user_order_inline
# 路由算法
shardingAlgorithms
:
# 库-路由算法 2是两个库,库的数量。库的数量用哈希模2来计算。
database_inline
:
type
:
INLINE
props
:
algorithm-expression
:
ds_$->{Math.abs(user_id.hashCode()) % 2}
# 表-路由算法 4是一个库里,表的数量。4 - 1 为了获得 011 这样的二进制值。不推荐 user_order_$->{Math.abs(user_id.hashCode()) % 2} 作为表的路由
user_order_inline
:
type
:
INLINE
props
:
algorithm-expression
:
user_order_$->{(user_id.hashCode() ^ (user_id.hashCode()) >>> 16) & (4 - 1)}
props
:
# 是否在日志中打印 SQL。
# 打印 SQL 可以帮助开发者快速定位系统问题。日志内容包含:逻辑 SQL,真实 SQL 和 SQL 解析结果。
# 如果开启配置,日志将使用 Topic ShardingSphere-SQL,日志级别是 INFO。 false
sql-show
:
true
# 是否在日志中打印简单风格的 SQL。false
sql-simple
:
true
# 用于设置任务处理线程池的大小。每个 ShardingSphereDataSource 使用一个独立的线程池,同一个 JVM 的不同数据源不共享线程池。
executor-size
:
20
# 查询请求在每个数据库实例中所能使用的最大连接数。1
max-connections-size-per-query
:
1
# 在程序启动和更新时,是否检查分片元数据的结构一致性。
check-table-metadata-enabled
:
false
# 在程序启动和更新时,是否检查重复表。false
check-duplicate-table-enabled
:
false
\ No newline at end of file
xfg-dev-tech-app/src/test/java/cn/bugstack/xfg/dev/tech/test/ApiTest.java
0 → 100644
浏览文件 @
e470682b
package
cn.bugstack.xfg.dev.tech.test
;
import
cn.bugstack.xfg.dev.tech.infrastructure.dao.IUserOrderDao
;
import
cn.bugstack.xfg.dev.tech.infrastructure.po.UserOrderPO
;
import
com.alibaba.fastjson2.JSON
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.lang3.RandomStringUtils
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.springframework.boot.test.context.SpringBootTest
;
import
org.springframework.test.context.junit4.SpringRunner
;
import
javax.annotation.Resource
;
import
java.math.BigDecimal
;
import
java.util.Date
;
import
java.util.List
;
import
java.util.UUID
;
@Slf4j
@RunWith
(
SpringRunner
.
class
)
@SpringBootTest
public
class
ApiTest
{
public
static
void
main
(
String
[]
args
)
{
System
.
out
.
println
(
10001L
%
2
);
}
@Resource
private
IUserOrderDao
userOrderDao
;
@Test
public
void
test_selectByUserId
()
{
List
<
UserOrderPO
>
list
=
userOrderDao
.
selectByUserId
(
"xfg_PrmgwQ"
);
log
.
info
(
"测试结果:{}"
,
JSON
.
toJSONString
(
list
));
}
@Test
public
void
test_insert
()
{
for
(
int
i
=
0
;
i
<
1000
;
i
++)
{
UserOrderPO
userOrderPO
=
UserOrderPO
.
builder
()
.
userName
(
"小傅哥"
)
.
userId
(
"xfg_"
+
RandomStringUtils
.
randomAlphabetic
(
6
))
.
userMobile
(
"+86 13521408***"
)
.
sku
(
"13811216"
)
.
skuName
(
"《手写MyBatis:渐进式源码实践》"
)
.
orderId
(
RandomStringUtils
.
randomNumeric
(
11
))
.
quantity
(
1
)
.
unitPrice
(
BigDecimal
.
valueOf
(
128
))
.
discountAmount
(
BigDecimal
.
valueOf
(
50
))
.
tax
(
BigDecimal
.
ZERO
)
.
totalAmount
(
BigDecimal
.
valueOf
(
78
))
.
orderDate
(
new
Date
())
.
orderStatus
(
0
)
.
isDelete
(
0
)
.
uuid
(
UUID
.
randomUUID
().
toString
().
replace
(
"-"
,
""
))
.
ipv4
(
"127.0.0.1"
)
.
ipv6
(
"2001:0db8:85a3:0000:0000:8a2e:0370:7334"
.
getBytes
())
.
extData
(
"{\"device\": {\"machine\": \"IPhone 14 Pro\", \"location\": \"shanghai\"}}"
)
.
build
();
userOrderDao
.
insert
(
userOrderPO
);
}
}
/**
* 路由测试
*/
@Test
public
void
test_idx
()
{
for
(
int
i
=
0
;
i
<
50
;
i
++)
{
String
user_id
=
"xfg_"
+
RandomStringUtils
.
randomAlphabetic
(
6
);
log
.
info
(
"测试结果 {}"
,
(
user_id
.
hashCode
()
^
(
user_id
.
hashCode
())
>>>
16
)
&
3
);
}
}
}
xfg-dev-tech-infrastructure/pom.xml
0 → 100644
浏览文件 @
e470682b
<?xml version="1.0" encoding="UTF-8"?>
<project
xmlns=
"http://maven.apache.org/POM/4.0.0"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
>
<modelVersion>
4.0.0
</modelVersion>
<parent>
<groupId>
cn.bugstack
</groupId>
<artifactId>
xfg-dev-tech-shardingjdbc
</artifactId>
<version>
1.0-SNAPSHOT
</version>
</parent>
<artifactId>
xfg-dev-tech-infrastructure
</artifactId>
<dependencies>
<dependency>
<groupId>
org.mybatis.spring.boot
</groupId>
<artifactId>
mybatis-spring-boot-starter
</artifactId>
</dependency>
<dependency>
<groupId>
org.apache.shardingsphere
</groupId>
<artifactId>
shardingsphere-jdbc-core
</artifactId>
</dependency>
<dependency>
<groupId>
org.projectlombok
</groupId>
<artifactId>
lombok
</artifactId>
</dependency>
</dependencies>
<build>
<finalName>
xfg-dev-tech-infrastructure
</finalName>
<plugins>
<plugin>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-compiler-plugin
</artifactId>
<configuration>
<source>
${java.version}
</source>
<target>
${java.version}
</target>
<compilerVersion>
${java.version}
</compilerVersion>
</configuration>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
xfg-dev-tech-infrastructure/src/main/java/cn/bugstack/xfg/dev/tech/infrastructure/dao/IUserOrderDao.java
0 → 100644
浏览文件 @
e470682b
package
cn.bugstack.xfg.dev.tech.infrastructure.dao
;
import
cn.bugstack.xfg.dev.tech.infrastructure.po.UserOrderPO
;
import
org.apache.ibatis.annotations.Mapper
;
import
java.util.List
;
@Mapper
public
interface
IUserOrderDao
{
void
insert
(
UserOrderPO
userOrderPO
);
void
updateOrderStatusByUserId
(
String
userId
);
List
<
UserOrderPO
>
selectByUserId
(
String
userId
);
}
xfg-dev-tech-infrastructure/src/main/java/cn/bugstack/xfg/dev/tech/infrastructure/po/UserOrderPO.java
0 → 100644
浏览文件 @
e470682b
package
cn.bugstack.xfg.dev.tech.infrastructure.po
;
import
lombok.AllArgsConstructor
;
import
lombok.Builder
;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
import
java.math.BigDecimal
;
import
java.util.Date
;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public
class
UserOrderPO
{
/** 自增ID */
private
Long
id
;
/** 用户姓名 */
private
String
userName
;
/** 用户编号 */
private
String
userId
;
/** 用户电话 */
private
String
userMobile
;
/** 商品编号 */
private
String
sku
;
/** 商品名称 */
private
String
skuName
;
/** 订单ID */
private
String
orderId
;
/** 商品数量 */
private
int
quantity
;
/** 商品价格 */
private
BigDecimal
unitPrice
;
/** 折扣金额 */
private
BigDecimal
discountAmount
;
/** 费率金额 */
private
BigDecimal
tax
;
/** 支付金额 */
private
BigDecimal
totalAmount
;
/** 订单日期 */
private
Date
orderDate
;
/** 订单状态 */
private
int
orderStatus
;
/** 逻辑删单 */
private
int
isDelete
;
/** 唯一索引 */
private
String
uuid
;
/** 设备地址 */
private
String
ipv4
;
/** 设备地址 */
private
byte
[]
ipv6
;
/** 扩展数据 */
private
String
extData
;
/** 更新时间 */
private
Date
updateTime
;
/** 创建时间 */
private
Date
createTime
;
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录