[Java 实现水平分表 2]

目录

前言:

常见的策略包括:

Java实现哈希分表策略是一种常见的分表策略:

配置分表策略

使用分表

插入数据需要按照分表策略将数据插入到对应的分表:

定义分表Mapper接口

插入数据

哈希算法分表涉及到的代码讲解:

分表查询讲解:

IN分表策略和BETWEEN 条件的分表策略 查询实现:


前言:

   水平分表需要考虑数据的一致性和查询效率等问题

常见的策略包括:

  • 取模分表策略:根据分表键的值,使用取模运算将数据分散到多个表中。

  • 范围分表策略:根据分表键的值,将数据按照一定的范围分散到多个表中,例如按照时间范围、地理位置范围等。

  • 哈希分表策略:根据分表键的哈希值,将数据分散到多个表中,可以使用一致性哈希算法等。

  • 轮询分表策略:将数据按照一定的顺序分散到多个表中,例如轮询、随机等。

  • 按业务分表策略:根据业务需求将数据分散到多个表中,例如按照用户ID、订单ID等。

Java实现哈希分表策略是一种常见的分表策略:

public class HashTableShardingStrategy implements TableShardingStrategy<MyTable> {

    @Override
    public String doEqualSharding(Collection<String> availableTargetNames, ShardingValue<MyTable> shardingValue) {
        // 根据分表键的哈希值,计算出目标表的名称
        // 例如,可以使用一致性哈希算法将数据分散到多个表中
        long value = shardingValue.getValue().getId();
        int index = Math.abs(Long.hashCode(value) % availableTargetNames.size());
        return "my_table_" + index;
    }

    @Override
    public Collection<String> doInSharding(Collection<String> availableTargetNames, ShardingValue<MyTable> shardingValue) {
        // 同上,处理IN条件的分表策略
        return null;
    }

    @Override
    public Collection<String> doBetweenSharding(Collection<String> availableTargetNames, ShardingValue<MyTable> shardingValue) {
        // 同上,处理BETWEEN条件的分表策略
        return null;
    }
}
  1. 配置分表策略

@Configuration
public class ShardingSphereConfig {

    @Bean
    public HashTableShardingStrategy hashTableShardingStrategy() {
        return new HashTableShardingStrategy();
    }

    @Bean
    public ShardingRule shardingRule(HashTableShardingStrategy hashTableShardingStrategy) {
        // 配置分片规则
        ShardingRule shardingRule = ShardingRule.builder()
                .tableShardingStrategy(new TableShardingStrategyConfiguration("my_table", hashTableShardingStrategy))
                .build();
        return shardingRule;
    }

    @Bean
    public DataSource dataSource(ShardingRule shardingRule) throws SQLException {
        // 配置数据源
        Map<String, DataSource> dataSourceMap = new HashMap<>();
        dataSourceMap.put("ds0", createDataSource("jdbc:mysql://localhost:3306/db0", "root", "root"));
        dataSourceMap.put("ds1", createDataSource("jdbc:mysql://localhost:3306/db1", "root", "root"));
        return ShardingDataSourceFactory.createDataSource(dataSourceMap, shardingRule, new Properties());
    }

    private DataSource createDataSource(String url, String username, String password) {
        // 创建数据源
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setJdbcUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        return dataSource;
    }
}
  1. 使用分表

@Service
public class MyTableServiceImpl implements MyTableService {

    @Autowired
    private MyTableMapper myTableMapper;

    @Override
    public List<MyTable> listByUserId(long userId) {
        // 根据分表键查询数据
        return myTableMapper.selectList(new QueryWrapper<MyTable>().eq("user_id", userId));
    }
}

插入数据需要按照分表策略将数据插入到对应的分表:

public class MyTable implements Serializable {

    private Long id;

    private Long userId;

    private String name;

    // 省略getter和setter方法
}
  1. 定义分表Mapper接口

public interface MyTableMapper extends BaseMapper<MyTable> {
}
  1. 插入数据

@Service
public class MyTableServiceImpl implements MyTableService {

    @Autowired
    private MyTableMapper myTableMapper;

    @Override
    public void insert(MyTable myTable) {
        // 根据分表键计算出目标表的名称
        String tableName = "my_table_" + Math.abs(Long.hashCode(myTable.getUserId()) % 2);
        // 设置目标表的名称
        myTable.setTableName(tableName);
        // 插入数据
        myTableMapper.insert(myTable);
    }
}
插入数据时,需要根据分表键计算出目标表的名称,然后将目标表的名称设置到实体类中,最后插入数据到对应的分表中。

哈希算法分表涉及到的代码讲解:

  • doEqualSharding TableShardingStrategy 接口中的一个方法,用于处理等值查询的分表策略。在使用分表时,查询语句中通常会包含分表键的等值查询条件,例如 SELECT * FROM my_table WHERE user_id = 123这时就需要根据分表键的值将查询分发到对应的分表中。
  • doEqualSharding 方法的作用就是根据分表键的值,计算出目标表的名称。具体实现可以根据分表键的值,使用取模运算、哈希算法、范围划分等方式将数据分散到多个表中,然后根据分表键的值计算出目标表的名称。
  • Collection<String> availableTargetNames 是分片规则中配置的数据源名称集合,用于指定数据源中的分表名称。在使用分表时,需要将数据分散到多个表中,每个表对应一个数据源。因此,需要在分片规则中配置数据源名称集合
  • createDataSourceMap 方法返回一个包含两个数据源的 Map 对象,其中键为数据源名称,值为数据源对象。在分片规则中,使用 dataSourceRule 方法将数据源配置到分片规则中,然后在分表策略中使用 availableTargetNames 参数获取数据源名称集合,根据分表键的值计算出目标表的名称。例如,在取模分表策略中,可以使用取模运算将数据分散到多个表中,然后根据分表键的值计算出目标表的名称

分表查询讲解:

  • 在使用分表时,查询语句中通常会包含分表键的等值查询条件,例如 SELECT * FROM my_table WHERE user_id = 123,这时就需要根据分表键的值将查询分发到对应的分表中。在 ShardingSphere 中,可以使用分片规则和分表策略来实现数据的分片和查询。
  • 在分片规则中,可以配置多个数据源和分表名称集合,然后在分表策略中根据分表键的值计算出目标表的名称,最终将查询分发到对应的数据源和分表中。在查询时,ShardingSphere 会自动将多个数据源中的查询结果合并成一个结果集返回。
  • 例如,在以下代码中,listByUserId 方法根据分表键 userId 查询数据,然后将查询结果合并成一个结果集返回:

IN分表策略和BETWEEN 条件的分表策略 查询实现:

在使用分表时,查询语句中可能会包含 IN 条件和 BETWEEN 条件,例如:

SELECT * FROM my_table WHERE user_id IN (1, 2, 3) 2SELECT * FROM my_table WHERE created_at BETWEEN '2022-01-01' AND '2022-01-31'

@Override
public Collection<String> doInSharding(Collection<String> availableTargetNames, ShardingValue<MyTable> shardingValue) {
    // 根据分表键的值,计算出目标表的名称集合
    // 例如,可以使用取模运算将数据分散到多个表中
    Collection<String> targetNames = new HashSet<>();
    for (Object value : shardingValue.getValues()) {
        long id = (long) value;
        int index = (int) (id % availableTargetNames.size());
        targetNames.add("my_table_" + index);
    }
    return targetNames;
}

doInSharding 方法根据分表键的值,计算出目标表的名称集合。由于 IN 条件中可能包含多个值,因此需要遍历所有值,然后根据分表键的值计算出目标表的名称,最终返回目标表的名称集合。

@Override
public Collection<String> doBetweenSharding(Collection<String> availableTargetNames, ShardingValue<MyTable> shardingValue) {
    // 根据分表键的值,计算出目标表的名称集合
    // 例如,可以使用取模运算将数据分散到多个表中
    Collection<String> targetNames = new HashSet<>();
    Range<Long> range = shardingValue.getValueRange();
    for (long i = range.lowerEndpoint(); i <= range.upperEndpoint(); i++) {
        int index = (int) (i % availableTargetNames.size());
        targetNames.add("my_table_" + index);
    }
    return targetNames;
}

doBetweenSharding 方法根据分表键的值,计算出目标表的名称集合。由于 BETWEEN 条件中包含一个范围,因此需要遍历范围内的所有值,然后根据分表键的值计算出目标表的名称,最终返回目标表的名称集合。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
一、Sharding-JDBC 与 JOOQ 的兼容性测试 - **测试项** <br/> - 不分片时,使用默认数据源的增、删、改、查<br/> - 分片时,使用`ShardingDataSource`数据源的增、删、改、查<br/> - 分片表与不分片表的连表查询<br/> - 分片表的分页查询<br/> - 单路由单个字段的查询<br/> - 全路由 count 查询<br/> - 全路由 max 查询<br/> - 不分片表的事务<br/> - 分片表的事务<br/> - 维护不分片表和分片表的表操作在同一个事务中<br/> - **结论:** 本项目主要测试 Sharding-JDBC 与 JOOQ 的兼容性,就测试结果来看,所以测试项均兼容 ## 二、Sharding-JDBC VS JDBC 性能测试<br/> - **压测环境:MacBook Pro,处理器:2.3GHz、双核、Intel Core i5,内存:8GB、2133MHz LPDDR3**<br/> - **分片数量:30**<br/> - **测试数据基数:一百万条左右**<br/> - **压测汇总表**<br/> - **分片:** 单库多表,通过 Sharding-JDBC 水平分表后操作<br/> - **不分片:** 单库单表,通过 JDBC 操作<br/> ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是汤圆丫

怎么 给1分?

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值