文章重在于提供思想,具体代码可以评论区留言博主,获取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,转载请注明。