Springboot shardingJDBC读写分离+数据分表

7 Springboot shardingJDBC

准备工作

  1. 数据库读写分离配置略
  2. 主库(写库) dbm,从库(读库) dbs
  3. 创建表t_user(id,username,age)
  4. 分表t_user -> t_user_0,t_user_1,t_user_2

读写分离

maven


    io.shardingsphere
    sharding-jdbc-spring-boot-starter
    3.1.0

application.yml

sharding:
  jdbc:
    datasource:
      names: dbm,dbs # 多个数据源的名称
      dbm: # 主库
        type: com.alibaba.druid.pool.DruidDataSource # 使用Druid连接池
        driverClassName: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/db_master?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
        username: root
        password: 12345678
        maxPoolSize: 10
      dbs: # 从库
        type: com.alibaba.druid.pool.DruidDataSource
        driverClassName: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/db_slaver?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
        username: root
        password: 12345678
        maxPoolSize: 10
    config:
      masterslave: # 配置读写分离
        load-balance-algorithm-type: round_robin # 配置从库选择策略,提供轮询与随机【random 随机 ;round_robin 轮询】
        name: dbs
        master-data-source-name: dbm # 主数据源名称
        slave-data-source-names: dbs # 从数据源名称,多个用逗号隔开
      props:
        sql:
          show: true # 打印SQL
spring:
  main:
    allow-bean-definition-overriding: true # 由于shading-jdbc也会创建bean=Datasource,必须开启覆盖
logging:
  level:
    com.jf.mapper: DEBUG

mybatis配置

@Configuration
@MapperScan(basePackages = {DataConfig.mapperPackage}, sqlSessionFactoryRef = "sqlSessionFactory")
@EnableTransactionManagement
public class DataConfig {

    private Logger logger = LoggerFactory.getLogger(DataConfig.class);

    public final static String mapperPackage = "com.jf.mapper";
    public final static String modelPackage = "com.jf.model";
    public final static String xmlMapperLocation = "classpath*:mapper/*.xml";

    @Bean(name = "sqlSessionFactory")
    @Primary
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) {
        try {
            SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
            bean.setDataSource(dataSource);
            // we MUST set the 'VFS' if you use jar
            bean.setVfs(SpringBootVFS.class);
            // 实体类位置
            bean.setTypeAliasesPackage(modelPackage);
            // 设置mapper.xml文件所在位置
            org.springframework.core.io.Resource[] resources = new PathMatchingResourcePatternResolver().getResources(xmlMapperLocation);
            bean.setMapperLocations(resources);
            return bean.getObject();
        } catch (Exception e) {
            logger.error("Database sqlSessionFactory create error!", e);
            return null;
        }
    }

    @Bean(name = "sqlSessionTemplate")
    @Primary
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

    /**
     * 事务管理
     *
     * @return
     */
    @Bean(name = "platformTransactionManager")
    @Primary
    public PlatformTransactionManager platformTransactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

}

UserMapper.xml

<mapper namespace="com.jf.mapper.UserMapper">

	<insert id="insert" parameterType="com.jf.model.User">
		INSERT INTO t_user (id, username, address, age) VALUES (#{id}, #{username}, #{address}, #{age})
	insert>

	<select id="findById" parameterType="int" resultType="com.jf.model.User">
		 SELECT * FROM t_user WHERE id = #{id}
	select>

mapper>

UserMapper

public interface UserMapper {
    int insert(User user);
    User findById(Integer id);
}

UserService

@Service
public class UserService {

    @Resource
    private UserMapper userMapper;

    public User findUserById(Integer id) {
        return userMapper.findById(id);
    }

    public void insertUser(Integer id, String username, Integer age) {
        User user = new User();
        user.setId(id);
        user.setUsername(username);
        user.setAge(age);
        userMapper.insert(user);
    }

}

测试

@RunWith(SpringRunner.class)
@SpringBootTest
public class AppTest {

    @Resource
    private UserService userService;

    @Test
    public void test1() {
        userService.insertUser(20, "name", 1);
    }

    @Test
    public void test2() {
        User user = userService.findUserById(10);
        System.out.println(user);
    }

}

分表

注释配置项:sharding.jdbc.config.masterslave,添加以下配置

sharding:
  jdbc:
    config: # *注意masterslave和sharding不能同时使用
      sharding: # 分表配置
        tables:
          t_user: # 对应数据库表名
            actual-data-nodes: ds_0.t_user_$->{0..2} # 表示读取ds_0数据源的t_user_0,t_user_1,t_user_2
            table-strategy: # 策略
              standard:
                sharding-column: id # 根据id来区分(id值必须存在)
                precise-algorithm-class-name: com.jf.config.MyPreciseShardingAlgorithm # 配置数据分表的策略的类
        master-slave-rules: # 配置主从库
          ds_0:
            load-balance-algorithm-type: round_robin
            master-data-source-name: dbm
            slave-data-source-names: dbs

自定义策略
根据id取模(3)来获取表名,也可以根据id范围来决策表

public class MyPreciseShardingAlgorithm implements PreciseShardingAlgorithm<Integer> {
    @Override
    public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Integer> shardingValue) {
        for (String tableName : availableTargetNames) {
            if (tableName.endsWith(shardingValue.getValue() % 3 + "")) {
                return tableName;
            }
        }
        throw new IllegalArgumentException();
    }
}

测试日志:

Actual SQL: ds_0 ::: INSERT INTO t_user_2 (id, username, address, age) VALUES (?, ?, ?, ?) ::: [[20, 333, null, 20]]

你可能感兴趣的:(数据库,#,MySQL)