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

相关推荐
爱喝水的鱼丶2 小时前
SAP-ABAP:S/4 HANA ABAP 新特性入门:与 ECC ABAP 的核心差异、架构优势与学习路径规划
运维·数据库·性能优化·sap·abap·hana·开发交流
余槐i9 小时前
PostgreSQL 函数索引报错 must be immutable:3种绕法与代价
数据库·后端·sql·postgresql·性能优化
数据库小学妹9 小时前
PostgreSQL表膨胀怎么办?autovacuum清不动的根因与排查命令
数据库·postgresql·表膨胀·mvcc·数据库运维
mister_guo9 小时前
MySQL-1267错误:排序规则冲突的原因与解决方案
数据库·mysql
骇客野人10 小时前
在麒麟操作系统上 分别安装 jdk1.8, 达梦数据库,redis ,memcache 的操作实施方案和步骤
数据库·redis·memcached
美狐美颜SDK开放平台11 小时前
直播APP如何实现美白滤镜功能?视频美颜SDK技术开发方案详解
前端·数据库·人工智能·音视频·美颜sdk·直播美颜sdk·视频美颜sdk
花间相见13 小时前
【计算基础|MySQL01】【上手】安装连接、数据类型与建库建表
数据库·后端
花间相见13 小时前
【计算基础|MySQL02】【上手】SQL 增删改查
数据库·后端
ITxiaobing202313 小时前
IP 库与 AppsFlyer 国家/地区数据不一致,如何系统地对账?
数据库·网络协议·tcp/ip
这个DBA有点耶13 小时前
从时间到语义:时序数据库与向量数据库的核心机制、选型与多模融合趋势
数据库·mysql·架构