Spring mvc 接入 shardingsphere5.0.0 自定义表分片规则_springpmvc shardingsphere-程序员宅基地

技术标签: JAVA  mysql  mvc  sharding  电商  

背景

最近在搞数据迁移,之前存储的介质为mongo,集团层面在推动mongo下线,所以迁移到mySql是主流趋势,mongo目前共6分片,总数大概40亿左右,mySql承接的话,设计为32个库,每个库128个表。数据库的分片,中间件团队已经做了,我们需要处理的是路由到表这块的处理

前置官方资料

https://shardingsphere.apache.org/document/ 选择5.0.0版本进行阅读

Overview

ShardingSphere-JDBC Architecture

使用Spring boot 能很快结束开发,使用Spring mvc实属无奈,但是旧系统升级重构时间长,改造成本大,时间紧迫,只能先接入再说后续升级。

写在前面的话

为什么选择5.0.0版本作为最终的使用的版本

  1. 之前在很久之前,使用过dangdang 1.4.1版本的sharding jdbc,版本太老了,而且这个dangdang的版本已经不维护了。

  2. 所以决定使用 sharding -jdbc 3.x.x ,这个时候坐标变成了 io.shardingsphere 但是在网上查询发现,有内存泄漏的问题,于是转战4.x.x

  3. 到了4.x.x版本,此时坐标变成了org.apache.shardingsphere,又发现启动特别慢,启动的时候回查询所有表的信息,非常不合理,我们表又特别多,大概5000张以上,这个时候,启动就要5分钟,非常不能接受

  4. 今年11月份,发布了5.0.0,解决了上面的一些问题,终于能够正常使用了,但是又遇到了与数据库连接池、guava版本兼容性的问题,但好在,能用。

  5. sharding jdbc 也算尝试了很多个版本了,发现最大的问题就是,版本之间基本上没什么关系,包括namespace 、配置方式 、tag标 每个版本区别多很大,而且官方介绍的文档不是很详细,从github专门去下载了 example ,发现没有覆盖想要的例子,定眼一看,没有我用的版本!

下面开始搞事情!

接入shardingSphere

maven依赖

<dependency>
  <groupId>org.apache.shardingsphere</groupId>
  <artifactId>shardingsphere-jdbc-core</artifactId>
  <version>${sharding.sphere.version}</version>
</dependency>
<dependency>
  <groupId>org.apache.shardingsphere</groupId>
  <artifactId>shardingsphere-jdbc-core-spring-namespace</artifactId>
  <version>${sharding.sphere.version}</version> 
</dependency>

<properties>
	<sharding.sphere.version>5.0.0</sharding.sphere.version>
</properties>

已知版本冲突问题

shardingSphere5 对druid 的版本有要求,低版本有不兼容的情况,我目前使用的版本为1.2.8,没有发现兼容问题。使用其他连接池需要自行测试兼容性

同时对guava的版本也存在兼容性问题,我使用的版本为27.1-jre,没有发现问题。

<dependency>
 <groupId>com.alibaba</groupId>
 <artifactId>druid</artifactId>
 <version>1.2.8</version>
</dependency>

<dependency>
	<groupId>com.google.guava</groupId>
	<artifactId>guava</artifactId>
	<version>27.1-jre</version>
</dependency>

配置原有数据源

此时配置的是原始的数据库连接,和sharding jdbc还没有关联,正常使用什么连接池都可以

<bean id="dataSourcePro" class="com.alibaba.druid.pool.DruidDataSource">
  <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
  <property name="url" value="${db.url}"/>
  <property name="username" value="${ldb.username}"/>
  <property name="password" value="${db.password}"/>
  <property name="timeBetweenEvictionRunsMillis" value="3600000"/>
  <property name="minEvictableIdleTimeMillis" value="3600000"/>
  <property name="maxActive" value="150"/>
  <property name="minIdle" value="3"/>
  <property name="maxIdle" value="10"/>
  <property name="validationQuery" value="SELECT 1"/>
</bean>

nameSpace配置:

两个nameSpace分别对应shardingSphere的数据源处理与分片规则的处理

xmlns:shardingsphere="http://shardingsphere.apache.org/schema/shardingsphere/datasource"
xmlns:sharding="http://shardingsphere.apache.org/schema/shardingsphere/sharding"

scheme配置:

http://shardingsphere.apache.org/schema/shardingsphere/datasource
http://shardingsphere.apache.org/schema/shardingsphere/datasource/datasource.xsd

http://shardingsphere.apache.org/schema/shardingsphere/sharding                      http://shardingsphere.apache.org/schema/shardingsphere/sharding/sharding.xsd

配置sharding的dataSource

data-source-names填写刚才定义的dataSource,因为我这边只用到了单库所以只配置了一个数据库名称

具体分表的规则见:shardingRule

<!-- 配置ShardingSphereDataSource -->
<shardingsphere:data-source id="shardingDataSource" data-source-names="dataSourcePro"
  rule-refs="shardingRule">
  <props>
    <prop key="sql-show">false</prop>
  </props>
</shardingsphere:data-source>

配置sharding 的rule

  • logic-table 指的是不加后缀的原始表
  • actual-data-nodes 具体的表,从0到127,通过表达式表达出来,且前边需要加上数据源,为原本的数据源
  • table-strategy-ref指的是分表策略
<!-- 配置sharding策略 -->
<!--默认不分库(default-database-strategy-ref) 不分表(default-table-strategy-ref)-->
<sharding:rule id="shardingRule" default-database-strategy-ref="" default-table-strategy-ref="">
  <sharding:table-rules>
    <sharding:table-rule logic-table="trx_lot_relation_group"
      actual-data-nodes="dataSourcePro.trx_lot_relation_group_$->{0..127}"
      table-strategy-ref="groupLotRelationTableStrategy"
    />
  </sharding:table-rules>
</sharding:rule>

表的路由规则

  • sharding-column 指的是分表字段
  • algorithm-ref 指的是分表具体的算法
<!-- 表路由规则-->
<sharding:standard-strategy id="groupLotRelationTableStrategy" sharding-column="sku_id"
  algorithm-ref="groupLotRelationTableAlgorithmRef"/>

具体的算法规则

  • type=“CLASS_BASED” 指的是基于java类的处理
  • standard 指的是标准分片,包含着精确分片和区间分片(range)
  • algorithmClassName 为具体的实现类
<sharding:sharding-algorithm id="groupLotRelationTableAlgorithmRef" type="CLASS_BASED">
  <props>
    <prop key="strategy">standard</prop>
    <prop key="algorithmClassName">com.lbm.core.mysql.sharding.table.GroupLotRelationTableAlgorithm</prop>
  </props>
</sharding:sharding-algorithm>

mybatis session处理

这个时候dataSource填写刚才配置的shardingDataSource

<!--sharding datasource 接管 pro数据源 -->
<bean id="sessionFactoryPro" class="org.mybatis.spring.SqlSessionFactoryBean">
  <property name="dataSource" ref="shardingDataSource"/>
  <property name="configLocation" value="classpath:spring/mybatis-config.xml"/>
  <property name="mapperLocations" value="classpath:mapper/*.xml"/>
</bean>

配置事务

此时dataSource为新配置的shardingDataSource,否则事务不会生效

<bean id="transactionManagerPro"
  class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <property name="dataSource" ref="shardingDataSource"/>
  <qualifier value="transactionManagerPro"/>
</bean>

<tx:annotation-driven transaction-manager="transactionManagerPro" proxy-target-class="true"/>

mybatis mapperConfig配置

mapper扫描与session注入

<!--JED主库配置-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
  <property name="basePackage" value="com.lbm.core.mysql.lbmpro"/>
  <property name="sqlSessionFactoryBeanName" value="sessionFactoryPro"/>
</bean>

全部源码配置

数据源配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:tx="http://www.springframework.org/schema/tx"
  xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

  <bean id="lbmDataSourcePro" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="${lbm.pro.db.url}"/>
    <property name="username" value="${lbm.pro.db.username}"/>
    <property name="password" value="${lbm.pro.db.password}"/>
    <property name="timeBetweenEvictionRunsMillis" value="3600000"/>
    <property name="minEvictableIdleTimeMillis" value="3600000"/>
    <property name="maxActive" value="150"/>
    <property name="minIdle" value="3"/>
    <property name="maxIdle" value="10"/>
    <property name="validationQuery" value="SELECT 1"/>
  </bean>


  <!--JED主库配置-->
  <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="com.lbm.core.mysql.lbmpro"/>
    <property name="sqlSessionFactoryBeanName" value="sessionFactoryPro"/>
  </bean>

  <bean id="transactionManagerPro"
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="shardingDataSource"/>
    <qualifier value="transactionManagerPro"/>
  </bean>

  <tx:annotation-driven transaction-manager="transactionManagerPro" proxy-target-class="true"/>

  <!--sharding datasource 接管 pro数据源 -->
  <bean id="sessionFactoryPro" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="shardingDataSource"/>
    <property name="configLocation" value="classpath:spring/mybatis-config.xml"/>
    <property name="mapperLocations" value="classpath:mapper/*.xml"/>
  </bean>

  <!--sharding jdbc配置-->
  <import resource="classpath:spring/spring-config-sjdbc.xml"/>
</beans>

shardingJdbc配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:context="http://www.springframework.org/schema/context"
  xmlns:sharding="http://shardingsphere.apache.org/schema/shardingsphere/sharding"
  xmlns:shardingsphere="http://shardingsphere.apache.org/schema/shardingsphere/datasource"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://shardingsphere.apache.org/schema/shardingsphere/sharding
                        http://shardingsphere.apache.org/schema/shardingsphere/sharding/sharding.xsd
                        http://shardingsphere.apache.org/schema/shardingsphere/datasource
                           http://shardingsphere.apache.org/schema/shardingsphere/datasource/datasource.xsd
                        http://www.springframework.org/schema/context
                      http://www.springframework.org/schema/context/spring-context-3.0.xsd">


  <!-- 事务关系表路由规则-->
  <sharding:standard-strategy id="groupLotRelationTableStrategy" sharding-column="sku_id"
    algorithm-ref="groupLotRelationTableAlgorithmRef"/>

  <sharding:sharding-algorithm id="groupLotRelationTableAlgorithmRef" type="CLASS_BASED">
    <props>
      <prop key="strategy">standard</prop>
      <prop key="algorithmClassName">com.lbm.core.mysql.sharding.table.GroupLotRelationTableAlgorithm</prop>
    </props>
  </sharding:sharding-algorithm>
  <context:property-placeholder ignore-unresolvable="true"/>

  <!-- 配置ShardingSphereDataSource -->
  <shardingsphere:data-source id="shardingDataSource" data-source-names="lbmDataSourcePro"
    rule-refs="shardingRule">
    <props>
      <prop key="sql-show">false</prop>
    </props>
  </shardingsphere:data-source>
  <!-- 配置sharding策略 -->
  <!--默认不分库(default-database-strategy-ref) 不分表(default-table-strategy-ref)-->
  <sharding:rule id="shardingRule" default-database-strategy-ref="" default-table-strategy-ref="">
    <sharding:table-rules>
      <sharding:table-rule logic-table="trx_lot_relation_group"
        actual-data-nodes="lbmDataSourcePro.trx_lot_relation_group_$->{0..127}"
        table-strategy-ref="groupLotRelationTableStrategy"
      />
    </sharding:table-rules>
  </sharding:rule>

</beans>

具体的分片算法

package com.lbm.core.mysql.sharding.table;

import java.util.Collection;
import org.apache.shardingsphere.sharding.api.sharding.standard.PreciseShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.RangeShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.StandardShardingAlgorithm;
import org.springframework.stereotype.Component;

/**
 * groupLotRelation分表策略
 *
 * @author wangzy-nice
 * @date 2021-12-08 22:02
 */
@Component
public class GroupLotRelationTableAlgorithm implements StandardShardingAlgorithm<String> {
    

  /**
   * 区间分片
   *
   * @param tableNames
   * @param rangeShardingValue
   * @return
   */
  @Override
  public Collection<String> doSharding(Collection<String> tableNames,
      RangeShardingValue<String> rangeShardingValue) {
    
    throw new UnsupportedOperationException("暂未支持区间查询");
  }

  /**
   * 精确分片
   *
   * @param tableNames
   * @param preciseShardingValue
   * @return
   */
  @Override
  public String doSharding(Collection<String> tableNames,
      PreciseShardingValue<String> preciseShardingValue) {
    
    for (String key : tableNames) {
    
      if (key.endsWith(String.valueOf(Long.parseLong(preciseShardingValue.getValue()) % 128))) {
    
        return key;
      }
    }
    throw new UnsupportedOperationException();
  }

  @Override
  public void init() {
    
  }

  @Override
  public String getType() {
    
    return "GROUP_LOT_RELATION";
  }
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_34370153/article/details/122089238

智能推荐

【Android的事件处理】-----基于监听的事件处理_基于监听的事件处理含义-程序员宅基地

文章浏览阅读779次。单词知识:一、知识点 1、定义:为用户动作提供响应的机制就是事件处理。2、Android提供了两套强大的事件处理机制:基于监听的事件处理 基于回调的事件处理3、区别:一般来说,基于回调的事件处理可用于处理一些通用性的事件,基于回调的事件处理代码会比较简洁;但是对于某些特定的事件,无法使用基于回调的事件处 理,只能采用监听的事件处理。4、_基于监听的事件处理含义

onedrive共享文件_如何从OneDrive共享内容-程序员宅基地

文章浏览阅读7.3k次。onedrive共享文件If you’ve got an Office 365 account (free or paid), then you’ve got OneDrive, Microsoft’s cloud storage app. Cloud storage is great for sharing files with other people, so let’s see how it..._onedrive 共享

Android:项目模块化/组件化的架构之路(一)_android 模块化-程序员宅基地

文章浏览阅读1.8w次,点赞10次,收藏92次。随着技术越来越成熟,这两年,组件化开发与插件化开发的热度一度高涨。对于组件化,有的人也喜欢称之为模块化开发,我也比较喜欢称之为模块化开发。使用模块化开发也已经有一段时间了,特此总结一下模块化开发的心得,防止以后忘记。什么是模块化开发对于模块化开发的概念,有的人可能还不是很了解,通俗的来讲就是:将项目中的具体功能模块,如登录、个人中心等,拆分成一个一个单独的module,将其中公用的功..._android 模块化

JVM系列篇:JVM性能调优的6大步骤,及关键调优参数详解-程序员宅基地

文章浏览阅读1.9k次。2019独角兽企业重金招聘Python工程师标准>>> ..._jvm调优

【MATLAB】一种偶然性更小的抽奖代码-程序员宅基地

文章浏览阅读1.2k次,点赞2次,收藏4次。一种偶然性更小的抽奖代码。由于突发事件,需要进行“抽奖”。大家都怕中奖,所以让我搞一个更“公平”的代码来抽。

ITK-SNAP 安装和使用_itk snp 安装知乎-程序员宅基地

文章浏览阅读7.2w次,点赞23次,收藏139次。一.下载ITK-SNAP 安装包下载资源链接:https://sourceforge.net/projects/itk-snap/?source=directory或者http://www.itksnap.org/pmwiki/pmwiki.php?n=Downloads.SNAP3本人下载的是 ITK-SNAP 3.0 ,ITK-SNAP 3.4 ,ITK-SNAP 3.6 三个..._itk snp 安装知乎

随便推点

实习周记-day6-程序员宅基地

文章浏览阅读201次。今天分析了一下项目结构,4个大模块,一个主要通信模块,一个底层处理模块,一个ui模块,一个自动化测试模块,看了通讯模块,最主要就是core跟rest小模块,理解项目最主要先看通调用过程,可以先用测试模块debug来查看调用过程,测试入口可能跟实际rest入口不同,但是可以很好的理解实际请求处理流程,看完处理流程再找入口就简单多了,每个人理解项目的方法不同,但是都是有一些通用技巧的。除了看项目之外,每日的排核酸真心累,打底一小时...

在Proteus中添加标号-程序员宅基地

文章浏览阅读4.1k次。1.Proteus中添加组件后双击引脚可以快速生成一个最近的端口。2.按A调出设置界面3.在String中写:net=H#,"H"可以换成自定义前缀。count为起始值,increment为增量。4.依次点击想要编号的引脚。转载于:https://www.cnblogs.com/viaduct/p/5842429.html..._proteus如何给引脚编号

unexpected token:name(m) 報錯解決方案_unexpected token: name (tosjisfunction) [./~/qrcod-程序员宅基地

文章浏览阅读9.6k次,点赞3次,收藏3次。这个报错,比较啃爹的 我直接上图我先来描述下问题:我正常webpack打包 vue的js 文件是没问题的,但是 在我压缩打包的时候就踹这个问题了 注意看报错 from UglifyJs 很明显就是 问题出在UglifyJs 我去查了下资料 原来我的版本 UglifyJs 是不支持 打包 包含ES6的代码的官方的文档是这么解释的 官方文_unexpected token: name (tosjisfunction) [./~/qrcode/lib/core/utils.js:1,0]

cocos2d-js热更新_cocos2d-js 热更-程序员宅基地

文章浏览阅读1.5k次。1. 热更新基本思路得到cocoachina论坛上fysp和akira_cn的帮助,理清了游戏热更新的思路:执行AssetsManager后,搜索路径增加了jsb.fileUtils.getWritablePath()目录,并且是优先搜索;需要热更新js不放在project.json中定义,等AssetsManager更新完了,用cc.loader.load动态加载;所以在js_cocos2d-js 热更

jenkins+pytest+allure自动化持续集成_jenkins+allure持续集成-程序员宅基地

文章浏览阅读486次。jenkins+pytest+allure自动化持续集成pytest的下载和启动下载启动注意事项allure的安装和使用allure的下载allure的环境的配置pytest+allure生成的测试报告github的准备git仓库的建立测试文件上传git仓库jenkins与git代码的关联jenkins的下载jenkins安装注意事项jenkins的启动jenkins的配置pytest的下载和启动下载打开终端输入pip install pytest直接安装即可启动直接在主目录输入命令即可启动_jenkins+allure持续集成

2022年最新内蒙古道路货物运输驾驶员模拟真题题库及答案_车辆技术管理条例考题-程序员宅基地

文章浏览阅读263次。百分百题库提供道路货物运输驾驶员考试试题、道路货物运输驾驶员考试预测题、道路货物运输驾驶员考试真题、道路货物运输驾驶员证考试题库等,提供在线做题刷题,在线模拟考试,助你考试轻松过关。题干:包车客运时客运企业应与包车人签订包车合同,明确行驶的线路、包车人员、时间、费用等内容。客运企业按照规定办理包车业务审批,按照约定的()运输。A.起始地、目的地和线路B.起始地、目的地和班车模式定点C.起始地、目的地和班车模式定线D.起始地、目的地答案:A题干:在道路危险货物运输过程._车辆技术管理条例考题

推荐文章

热门文章

相关标签