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 --

相关推荐
ltl3 小时前
Disaggregated DB 合集:Socrates、PolarDB、Taurus 的共同模式
数据库
Blossom i5 小时前
大数据预处理与采集实验一:使用Python操作MySQL数据库
数据库·mysql
雾时之林6 小时前
Linux--软件管理、源码包安装
linux·服务器·数据库
老纪的技术唠嗑局7 小时前
超级干货分享:中小企业使用 OceanBase 实践经验汇总
数据库
CLOUD ACE8 小时前
谷歌云代理|零售商Target 如何利用 Spanner Graph 提升零售发现体验并将数据库维护成本降低 50%
数据库·零售
AI大模型-小雄8 小时前
Codex写分页接口为什么越翻越慢?用Cursor Pagination解决重复与漏数据
大数据·数据库·elasticsearch·搜索引擎·chatgpt·后端开发·codex
少晓年8 小时前
从 MySQL 迁移到人大金仓 KingbaseES:完整指南与实践
数据库·mysql
SelectDB9 小时前
Apache Doris AI RAG 实战:从基础 RAG 到知识图谱增强的技术能力与选型
数据库
SelectDB9 小时前
电商企业 PostgreSQL 迁移 Apache Doris:80TB 分析数据统一平台技术能力与实践
数据库
SelectDB9 小时前
阶跃星辰 Agent 可观测:Apache Doris / SelectDB 的技术能力与实践
数据库