文章重在于提供思想,具体代码可以评论区留言博主,获取git查看项目源码
一、简单的分库分表
- 分库分表策略
- 分库分表
- 16个库, 每个库64个表,总量就是 1024个表
- 分片键:短链码 code
- 比如 dbc655.top/03TGva的短链码 03TGva
- 分库分表算法:短链码进行hash取模
-
库ID = 短链码hash值 % 库数量 表ID = 短链码hash值 / 库数量 % 表数量
-
- 分库分表
- 优点
- 保证数据较均匀的分散落在不同的库、表中,可以有效的避免热点数据集中问题,
- 分库分表方式清晰易懂
- 问题
- 扩容不是很方便,需要数据迁移
- 需要一次性建立16个库, 每个库64个表,总量就是 1024个表,浪费资源
二、进阶的分库分表(具体如下图所示)
为啥能做到免迁移扩容?
- A92AEva1
- 由于短链码的前缀和后缀是是固定的,所以扩容也不影响旧的数据
- 类似的免迁移扩容策略还有哪些?
- 时间范围分库分表
- id范围分库分表
三、开始实战
1.首先先建好数据库和表(数据库-> 3 个 ,表 -> 6个)
2.自定义分片策略编写,有一个小例子,也可以到这里看看,这个例子会更加的简单,效果有点类似
CustomDBPreciseShardingAlgorithm
点击查看完整内容
package net.dbc.strategy;
import net.dbc.enums.BizCodeEnum;
import net.dbc.exception.BizException;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;
import java.util.Collection;
/**
* @author DBC
* @version 1.0.0
* @date 2022年12月03日 17:10:15
* @website dbc655.top
*/
public class CustomDBPreciseShardingAlgorithm implements PreciseShardingAlgorithm<String> {
/**
* @param availableTargetNames 数据源集合
* 在分库时值为所有分片库的集合 databaseNames
* 分表时为对应分片库中所有分片表的集合 tablesNames
* @param shardingValue 分片属性,包括
* logicTableName 为逻辑表,
* columnName 分片健(字段),
* value 为从 SQL 中解析出的分片健的值
* @return
*/
@Override
public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<String> shardingValue) {
//获取短链码第一位,即库位
String codePrefix = shardingValue.getValue().substring(0, 1);
for (String targetName : availableTargetNames) {
//获取库名的最后一位,真实配置的ds
String targetNameSuffix = targetName.substring(targetName.length() - 1);
//如果一致则返回
if (codePrefix.equals(targetNameSuffix)) {
return targetName;
}
}
//抛异常
throw new BizException(BizCodeEnum.DB_ROUTE_NOT_FOUND);
}
}
CustomTablePreciseShardingAlgorithm
点击查看完整内容
package net.dbc.strategy;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;
import java.util.Collection;
/**
* @author DBC
* @version 1.0.0
* @date 2022年12月03日 17:19:18
* @website dbc655.top
*/
public class CustomTablePreciseShardingAlgorithm implements PreciseShardingAlgorithm<String> {
/**
* @param availableTargetNames 数据源集合
* 在分库时值为所有分片库的集合 databaseNames
* 分表时为对应分片库中所有分片表的集合 tablesNames
* @param shardingValue 分片属性,包括
* logicTableName 为逻辑表,
* columnName 分片健(字段),
* value 为从 SQL 中解析出的分片健的值
* @return
*/
@Override
public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<String> shardingValue) {
//获取逻辑表
String targetName = availableTargetNames.iterator().next();
//短链码 a23Ad1
String value = shardingValue.getValue();
//获取短链码最后一位
String codeSuffix = value.substring(value.length()-1);
//拼接Actual table
return targetName+"_"+codeSuffix;
}
}
3.配置文件添加相应的代码
#----------短链,策略:分库+分表--------------
# 先进行水平分库,然后再水平分表
spring.shardingsphere.sharding.tables.short_link.database-strategy.standard.sharding-column=code
spring.shardingsphere.sharding.tables.short_link.database-strategy.standard.precise-algorithm-class-name=net.dbc.strategy.CustomDBPreciseShardingAlgorithm
# 水平分表策略,自定义策略。 真实库.逻辑表
spring.shardingsphere.sharding.tables.short_link.actual-data-nodes=ds0.short_link,ds1.short_link,dsa.short_link
spring.shardingsphere.sharding.tables.short_link.table-strategy.standard.sharding-column=code
spring.shardingsphere.sharding.tables.short_link.table-strategy.standard.precise-algorithm-class-name=net.dbc.strategy.CustomTablePreciseShardingAlgorithm
#id生成策略
spring.shardingsphere.sharding.tables.short_link.key-generator.column=id
spring.shardingsphere.sharding.tables.short_link.key-generator.type=SNOWFLAKE
spring.shardingsphere.sharding.tables.short_link.key-generator.props.worker.id=${workerId} 基本的配置文件一览
4.短链码前缀、后缀,库表位的生成
ShardingDBConfig
点击查看完整内容
package net.dbc.strategy;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
/**
* @author DBC
* @version 1.0.0
* @date 2022年12月03日 17:27:11
* @website dbc655.top
*/
public class ShardingDBConfig {
/**
* 存储数据库位置编号
*/
private static final List<String> dbPrefixList = new ArrayList<>();
private static Random random = new Random();
//配置启用那些库的前缀
static {
dbPrefixList.add("0");
dbPrefixList.add("1");
dbPrefixList.add("a");
}
/**
* 获取随机的前缀
* @return
*/
public static String getRandomDBPrefix(){
int index = random.nextInt(dbPrefixList.size());
return dbPrefixList.get(index);
}
} ShardingTableConfig
点击查看完整内容
package net.dbc.strategy;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
/**
* @author DBC
* @version 1.0.0
* @date 2022年12月03日 17:27:52
* @website dbc655.top
*/
public class ShardingTableConfig {
/**
* 存储数据表位置编号
*/
private static final List<String> tableSuffixList = new ArrayList<>();
private static Random random = new Random();
//配置启用那些表的后缀
static {
tableSuffixList.add("0");
tableSuffixList.add("a");
}
/**
* 获取随机的后缀
* @return
*/
public static String getRandomTableSuffix(){
int index = random.nextInt(tableSuffixList.size());
return tableSuffixList.get(index);
}
} 四、简单测试短链码的生成、查询
@Autowired
private ShortLinkManager shortLinkManager;
@Test
public void testSaveShortLink() {
Random random = new Random();
for (int i = 0; i < 100; i++) {
int num1 = random.nextInt(10);
int num2 = random.nextInt(100000000);
int num3 = random.nextInt(100000000);
String originalUrl = num1 + ".dbc655" + num2 + ".top" + num3;
String shortLinkCode = shortLinkComponent.createShortLinkCode(originalUrl);
ShortLinkDO shortLinkDO = new ShortLinkDO();
shortLinkDO.setCode(shortLinkCode);
shortLinkDO.setAccountNo((long) num3);
shortLinkDO.setSign(CommonUtil.MD5(originalUrl));
shortLinkDO.setDel(0);
shortLinkManager.addShortLink(shortLinkDO);
}
}
@Test
public void testFind(){
ShortLinkDO shortLinCode = shortLinkManager.findByShortLinCode("031WWqNa");
log.info(shortLinCode.toString());
}
本文作者为DBC,转载请注明。



