apache-shardingsphere-5.5.3自定义分片算法

一、需求

1、微服务拆分,服务拆成了多个,mysql数据库也拆成了多个,但是要求新旧服务可以切换,可以并行,所以需要对原有服务实现一个逻辑库来伪装未拆分前的数据库。

2、其中某个配置表在多个库中都存在,在多个库里的表名也相同,但记录里的某个字段取值不会重复,且取值范围大概100多个。

3、通过判断读写sql中的这个字段的取值来选择数据库,也就是维护一个字段值到数据库的map。

4、需要支持Mysql8.x。

Mycat1.6的枚举分片可以支持需求,但是Mycat1.6不支持Mysql8.x,主要卡在用户登录认证方式上,总提示密码错误无法建立连接,且新版Mycat2.0官方缺少维护,连下载页面都打不开了。

apache-shardingsphere-5.5.3可以支持Mysql8.x,但是现有的分片算法不支持需求,需要自己实现一个分片算法类。

二、代码实现

1、代码文件:KeyMappingShardingAlgorithm.java

java 复制代码
package com.example.sharding;

import org.apache.shardingsphere.sharding.api.sharding.standard.RangeShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.StandardShardingAlgorithm;
import org.apache.shardingsphere.sharding.api.sharding.standard.PreciseShardingValue;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Properties;
import java.util.stream.Collectors;

public class KeyMappingShardingAlgorithm implements StandardShardingAlgorithm<String> {

    private Map<String, String> keyMap;
    private String defaultDs = "db0";

    @Override
    public void init(Properties props) {
        String mapFile = props.getProperty("mapFile");
        if (mapFile != null && !mapFile.isEmpty()) {
            try (InputStream in = new FileInputStream(mapFile)) {
                Properties mapProps = new Properties();
                mapProps.load(in);
                keyMap = mapProps.entrySet().stream()
                        .collect(Collectors.toMap(
                                e -> e.getKey().toString(),
                                e -> e.getValue().toString()
                        ));
            } catch (IOException e) {
                throw new RuntimeException("Failed to load mapping file: " + mapFile, e);
            }
        } else {
            keyMap = Collections.emptyMap();
        }

        String defaultFromProps = props.getProperty("default");
        if (defaultFromProps != null && !defaultFromProps.isEmpty()) {
            defaultDs = defaultFromProps;
        }
    }

    @Override
    public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<String> shardingValue) {
        String key = shardingValue.getValue();
        String target = keyMap.get(key);
        if (target == null) {
            target = defaultDs;
        }
        return target;
    }

    @Override
    public Collection<String> doSharding(Collection<String> availableTargetNames, RangeShardingValue<String> shardingValue) {
        return availableTargetNames;
    }

    // getProps() 方法已删除,5.5.3 版本中不需要
}

--

2、通过脚本打包成jar

2.1 需要下载jdk,下载地址:Downloads for Amazon Corretto 25 - Amazon Corretto 25

2.2 设置JAVA_HOME、添加PATH等,让java、javac、jar命令可用。

2.3 打包脚本:

比如KeyMappingShardingAlgorithm.java放到KeyMappingShardingAlgorithm目录下:

同目录下存放build.sh脚本:

bash 复制代码
#!/bin/bash

set -e

# 1. 先编译
javac -cp "/path/to/shardingsphere-proxy/lib/*" KeyMappingShardingAlgorithm.java


# 2. 创建正确的目录结构
mkdir -p com/example/sharding
cp KeyMappingShardingAlgorithm.class com/example/sharding/


# 3. 打包(注意从当前目录开始)
jar cf key-mapping-sharding.jar com/example/sharding/KeyMappingShardingAlgorithm.class


# 4. 验证 JAR 内容
jar tf key-mapping-sharding.jar
# 应该输出:
# com/example/sharding/KeyMappingShardingAlgorithm.class


# 5. 检查 ext-lib 目录是否存在,不存在则创建
mkdir -p /path/to/shardingsphere-proxy/ext-lib/


# 6. 部署到 ext-lib
cp key-mapping-sharding.jar /path/to/shardingsphere-proxy/ext-lib/


# 7. 重启
#/path/to/shardingsphere-proxy/bin/start.sh 3307

执行脚本生成key-mapping-sharding.jar,并放到了/path/to/shardingsphere-proxy/ext-lib/目录下。

三、配置文件

1、在conf/database-sharding.yaml文件中的rules配置如下:

python 复制代码
databaseName: mydb

dataSources:
  db0:
    url: jdbc:mysql://10.10.10.16:3306/user_db?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
  db1:
    url: jdbc:mysql://10.10.10.17:3306/orders_db?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
    username: root
    password: 123456

rules:
  - !SHARDING
    tables:
      my_config:
        actualDataNodes: db0.my_config, db1.my_config
        databaseStrategy:
          standard:
            shardingColumn: config_key
            shardingAlgorithmName: enum-key-algorithm
      my_user:
        actualDataNodes: db0.my_user
      my_role:
        actualDataNodes: db0.my_role
      orders:
        actualDataNodes: db1.orders
      books:
        actualDataNodes: db1.books
    shardingAlgorithms:
        enum-key-algorithm:
          type: CLASS_BASED
          props:
            strategy: STANDARD
            algorithmClassName: com.example.sharding.KeyMappingShardingAlgorithm
            mapFile: ./conf/key-mapping.properties
            default: db0
  - !SINGLE
    defaultDataSource: db0

解释如下:

my_user表、my_role表的请求路由到物理库db0。

orders表、books表的请求路由到物理库db1。

my_config表的请求需要做分片,根据config_key字段使用enum-key-algorithm算法来分片。

enum-key-algorithm分片算法由类com.example.sharding.KeyMappingShardingAlgorithm实现,同时依赖./conf/key-mapping.properties文件作为输入。

在./conf/key-mapping.properties中未涉及的config_key字段取值将默认路由到db0。

2、./conf/key-mapping.properties文件内容如下:

bash 复制代码
# key 到数据源的映射
server_addr=db0
server_port=db0
orders_max=db1
books_max=db1

当config_key字段的取值为前面的key时,路由到后面的物理库。

3、另外还需要配置conf/global.yaml文件:

python 复制代码
# conf/global.yaml - 5.5.3 版本正确格式

# 1. 运行模式(必须,取代旧版的 proxy.database-name 和 proxy.port)
mode:
  type: Standalone
  repository:
    type: JDBC

# 2. 系统属性(原先 proxy.props 下的内容,提升到顶层 props)
props:
  proxy-frontend-flush-threshold: 128
  proxy-hint-enabled: false
  sql-show: true   # 建议开启,方便调试

# 3. 登录权限(原先 authority 部分,格式基本不变,但注意缩进)
authority:
  users:
    - user: root
      password: 123456
      admin: true
  privilege:
    type: ALL_PERMITTED

# 4. SQL 解析缓存(原先 sqlParser 部分)
sqlParser:
  sqlStatementCache:
    initialCapacity: 2000
    maximumSize: 65535
  parseTreeCache:
    initialCapacity: 128
    maximumSize: 1024

# 5. SQL 联邦查询(原先 sqlFederation 部分)
sqlFederation:
  sqlFederationEnabled: true
  executionPlanCache:
    initialCapacity: 2000
    maximumSize: 65535

# 设置默认事务类型为本地事务,禁用 Seata
transaction:
  defaultType: LOCAL

--

四、启动并验证

相关命令如下:

bash 复制代码
# 启动
/path/to/shardingsphere-proxy/bin/start.sh 3307

# 查看启动日志
tail -50 /path/to/shardingsphere-proxy/logs/stdout.log

# 登录mysql
mysql -h127.0.0.1 -P3307 -uroot -p'123456'

# 验证sql
SELECT * FROM my_config WHERE `config_key` = 'server_addr';
SELECT * FROM my_config WHERE `config_key` = 'orders_max';

--

-- end --

相关推荐
兜有米啦1 小时前
数据库第二次作业
数据库
nVisual2 小时前
机柜PDU安装位置与空间建模方案
大数据·网络·数据库·信息可视化·数据中心基础设施管理
weixin_6682 小时前
Cursor-superpowers插件用法
数据库·人工智能
NWU_白杨2 小时前
三种常用的数据存储技术
数据库·redis·mysql·sqlite
吃饱了得干活2 小时前
亿级订单表分库分表设计,从0到1全流程
java·数据库·面试
蓝创工坊Blue Foundry2 小时前
图片文字提取到 Excel:批量任务如何先定义要交付的字段
运维·服务器·开发语言·数据库·自动化·ocr·excel
麦聪聊数据3 小时前
企业数据市场建设(三):API 化服务封装,让数据开箱即用、避免重复开发
数据库
脱胎换骨-军哥3 小时前
C++数据库存储引擎内核开发:B+树索引与MVCC并发控制的完整实现
数据库·c++·b树
麦聪聊数据3 小时前
企业数据市场建设(四):流程闭环与价值运营,让数据市场真正转起来
运维·数据库