yml配置
server:
# 程序端口
port: 8095
spring:
application:
# 注册到 nacos 注册中心的服务名
name: iot
cloud:
nacos:
discovery:
# nacos 注册中心的地址
server-addr: 127.0.0.1:8848
freemarker:
checkTemplateLocation: false
main:
allow-bean-definition-overriding: true
# sharding-jdbc配置
shardingsphere:
# 是否开启SQL显示
props:
sql:
show: true
# ====================== ↓↓↓↓↓↓ 数据源配置 ↓↓↓↓↓↓ ======================
datasource:
names: ds-master-0,ds-master-1,ds-slave-0,ds-slave-1
# ====================== ↓↓↓↓↓↓ 配置第1个主从库 ↓↓↓↓↓↓ ======================
# 主库1
ds-master-0:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.73.100:3306/db_master?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF8&zeroDateTimeBehavior=convertToNull&useSSL=false # MySQL在高版本需要指明是否进行SSL连接 解决则加上 &useSSL=false
username: root
password: root
# 主库2
ds-master-1:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.73.100:3306/db_master1?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF8&zeroDateTimeBehavior=convertToNull&useSSL=false # MySQL在高版本需要指明是否进行SSL连接 解决则加上 &useSSL=false
username: root
password: root
# 主库1-从库
ds-slave-0:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.73.133:3306/db_master?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF8&zeroDateTimeBehavior=convertToNull&useSSL=false # MySQL在高版本需要指明是否进行SSL连接 解决则加上 &useSSL=false
username: root
password: root
# 主库2-从库
ds-slave-1:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.73.133:3306/db_master1?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF8&zeroDateTimeBehavior=convertToNull&useSSL=false # MySQL在高版本需要指明是否进行SSL连接 解决则加上 &useSSL=false
username: root
password: root
sharding:
# ====================== ↓↓↓↓↓↓ 分库分表配置 ↓↓↓↓↓↓ ======================
# 分库策略 => 根据user_id取模拆分到不同的库中
# default-database-strategy:
# inline:
# sharding-column: id
# algorithm-expression: ds-master-$->{id % 2}
# 分表策略
tables:
t_user:
#actual-data-nodes: ds-master-$->{0..1}.t_user$->{0..1}
actual-data-nodes: ds-master-0.t_user$->{2021..2022}
key-generator:
column: id # 主键ID
type: SNOWFLAKE # 生成策略
# 添加数据分表策略
table-strategy:
inline:
# 添加数据分表字段(根据字段插入数据到那个表 ex:id)
sharding-column: year
# 分片算法表达式 => 根据用户id取模拆分到不同的表中
algorithm-expression: t_user$->{year}
#按照创建时间的年月分表
# standard:
# preciseAlgorithmClassName: com.sc.sp.iot.config.DateShardingConfig
# sharding-column: createTime #要分片的列
# ====================== ↓↓↓↓↓↓ 读写分离配置 ↓↓↓↓↓↓ ======================
master-slave-rules:
ds-master-0:
# 主库
masterDataSourceName: ds-master-0
# 从库
slaveDataSourceNames:
- ds-slave-0
# 从库查询数据的负载均衡算法 目前有2种算法 round_robin(轮询)和 random(随机)
# 算法接口 org.apache.shardingsphere.spi.masterslave.MasterSlaveLoadBalanceAlgorithm
# 实现类 RandomMasterSlaveLoadBalanceAlgorithm 和 RoundRobinMasterSlaveLoadBalanceAlgorithm
loadBalanceAlgorithmType: ROUND_ROBIN
ds-master-1:
masterDataSourceName: ds-master-1
slaveDataSourceNames:
- ds-slave-1
loadBalanceAlgorithmType: ROUND_ROBIN
#配置mybatis-plus相关属性
mybatis-plus:
#配置mapper.xml文件读取位置信息
mapper-locations: classpath*:mapper/*.xml
#实体扫描,多个package用逗号或者分号分隔(在config中配置了此处不用配置)
#typeAliasesPackage: com.sc.cs.base.*.dao
# 全局mapper映射数据库配置
global-config:
db-config:
#主键生成策略
#id-type: UUID
#数据库大写下划线转换
capital-mode: false
#配置逻辑删除字段
logic-delete-value: 1
logic-not-delete-value: 0
refresh: true
configuration:
#配置返回数据库(column下划线 -> java驼峰式)
map-underscore-to-camel-case: false
#缓存配置false,默认全部重新读取
cache-enabled: false
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>4.0.0-RC1</version>
</dependency>
根据创建时间路由的配置类
package com.sc.sp.iot.config;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
/**
* 根据创建时间的年
*/
public class DateShardingConfig implements PreciseShardingAlgorithm<Date>{
@Override
public String doSharding(Collection<String> collection, PreciseShardingValue<Date> preciseShardingValue) {
//preciseShardingValue就是当前插入的字段值
//collection 内就是所有的逻辑表
//获取字段值
Date value = preciseShardingValue.getValue();
Calendar calendar = Calendar.getInstance();
calendar.setTime(value); //放入Date类型数据
System.out.println("value..."+value);
if(value == null){
throw new UnsupportedOperationException("value is null");
}
String tableTailName= "t_user"+calendar.get(Calendar.YEAR);
System.out.println("tableTailName.."+tableTailName);
for (String tableName : collection) {
//循环表名已确定使用哪张表
System.out.println("tableName..."+tableName);
if (tableName.equals(tableTailName)){
//表示相等就返回
System.out.println("tableName.."+tableName+"....tableTailName."+tableTailName);
return tableName;
}
}
return null;
}
}
总结
在开发中,随着时间的推移,数据量越来越大,采用分表之后,表越来越多,而shardingjdbc每次查询时如果查询条件没有找到分表的字段的等于条件,会查询所有分的表,采用笛卡尔积汇总数据再返回,此时按照上诉的按照年份分表的案列,可以在表中调价一个year字段存储年份
1.在查询时间范围时,判断范围在哪一年,直接设置year为那一年,这样shardingjdbc就只会查找对应年份的一张表
2.查询时一定要分页,避免数据库数据量过大而全表扫描造成内存溢出
3.如何平滑的增加字段
(1)初期数据量不大,直接alter修改
(2)提前添加多个无用字段,例如(A,B,C.....)
(3) 采用key-value类型数据库,redis,monogo等