天天看点

ShardingSphere Raw JDBC 主从示例ShardingSphere Raw JDBC 主从示例

ShardingSphere Raw JDBC 主从示例

总览

    这个示例不结合ORM之类的,直接执行SQL语句。通过写两个简单的文件就可以了,大致的步骤如下:

  • 1.配置Maven依赖
  • 2.配置文件写入相关配置
  • 3.获取DataSource类编写
  • 4.测试

配置Maven依赖

    其主要依赖如下,还有一些spring、mysql的依赖,总的Maven文件链接在这:pom.xml,自定查找添加吧

<dependency>
    <groupId>org.apache.shardingsphere</groupId>
	<artifactId>shardingsphere-jdbc-core</artifactId>
	<version>5.0.0-alpha</version>
</dependency>
           

application.properties文件写入

    写入主从库的相关配置

# 读写分离 - 数据库框架版本 2.0 ShardingSphere-jdbc 5.0.0-alpha
sharding.jdbc.datasource.names=master,slave0,slave1

sharding.jdbc.datasource.ds-master.driver-class-name=com.mysql.jdbc.Driver
sharding.jdbc.datasource.ds-master.url=jdbc:mysql://localhost:3306/test?serverTimezone=UTC&useUnicode=true\
  &characterEncoding=utf-8\
  &useSSL=false&allowPublicKeyRetrieval=true
sharding.jdbc.datasource.ds-master.username=root
sharding.jdbc.datasource.ds-master.password=root

sharding.jdbc.datasource.ds-slave0.driver-class-name=com.mysql.jdbc.Driver
sharding.jdbc.datasource.ds-slave0.url=jdbc:mysql://localhost:3309/test?serverTimezone=UTC&useUnicode=true\
  &characterEncoding=utf-8\
  &useSSL=false&allowPublicKeyRetrieval=true
sharding.jdbc.datasource.ds-slave0.username=root
sharding.jdbc.datasource.ds-slave0.password=root

sharding.jdbc.datasource.ds-slave1.driver-class-name=com.mysql.jdbc.Driver
sharding.jdbc.datasource.ds-slave1.url=jdbc:mysql://localhost:3310/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8\
  &useSSL=false&allowPublicKeyRetrieval=true
sharding.jdbc.datasource.ds-slave1.username=root
sharding.jdbc.datasource.ds-slave1.password=root
           

ShardingMasterSlaveDataSource编写

    这里默认使用HikariDataSource,思路主要是生成各个主从库的链接,放到Sharding中,代码中也有说明,总体比较简单:

package com.example.demo.shardingsphere.raw.jdbc;

import com.zaxxer.hikari.HikariDataSource;
import io.shardingsphere.api.config.MasterSlaveRuleConfiguration;
import io.shardingsphere.shardingjdbc.api.MasterSlaveDataSourceFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.*;

/**
 * @author lw
 */
@Slf4j
@Component
public class ShardingMasterSlaveDataSource {

    private final String DRIVER = ".driver-class-name";
    private final String URL = ".url";
    private final String USERNAME = ".username";
    private final String PASSWORD = ".password";
    private final String DBS = "sharding.jdbc.datasource.names";

    @Autowired
    private Environment environment;

    DataSource createDataSource() throws SQLException {
        // 获取数据库列表
        String[] dbs = Objects.requireNonNull(environment.getProperty(DBS)).split(",");
        log.info("DBS::" + Arrays.toString(dbs));

        // 设置主从,约定第一个为主,其他为从
        MasterSlaveRuleConfiguration configuration = new MasterSlaveRuleConfiguration(dbs[0], dbs[0],
                Arrays.asList(Arrays.copyOfRange(dbs, 1, dbs.length)));
        log.info("ShardingMasterSlaveDataSource master :: " + configuration.getMasterDataSourceName());
        log.info("ShardingMasterSlaveDataSource slave :: " + configuration.getSlaveDataSourceNames());

        // 设置打印SQL语句,查看主从配置和切换是否成功
        Properties properties = new Properties();
        properties.setProperty("sql.show", "true");

        return MasterSlaveDataSourceFactory.createDataSource(createDataSourceMap(dbs), configuration, new HashMap<>(0),
                properties);
    }

    /**
     * 返回DataSource列表
     */
    private Map<String, DataSource> createDataSourceMap(String[] dbs) {
        Map<String, DataSource> result = new HashMap<>(dbs.length);
        for (String db: dbs) {
            log.info("Create data source ::" + db);
            result.put(db, createDataSource("sharding.jdbc.datasource.ds-" + db));
        }
        return result;
    }

    private DataSource createDataSource(String prefix) {
        log.info(DRIVER + "::" + environment.getProperty(prefix + DRIVER));
        log.info(URL + "::" + environment.getProperty(prefix + URL));
        log.info(USERNAME + "::" + environment.getProperty(prefix + USERNAME));
        log.info(PASSWORD + "::" + environment.getProperty(prefix + PASSWORD));

        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setDriverClassName(environment.getProperty(prefix + DRIVER));
        dataSource.setJdbcUrl(environment.getProperty(prefix + URL));
        dataSource.setUsername(environment.getProperty(prefix + USERNAME));
        dataSource.setPassword(environment.getProperty(prefix + PASSWORD));
        return dataSource;
    }
}
           

测试

    直接生写SQL了,就不结合ORM之类的了,这里是通过日志看出是否生效的,日志大致如下

Sharding-Sphere-SQL                      : Rule Type: master-slave
Sharding-Sphere-SQL                      : SQL: select * from stores limit 5 ::: DataSources: slave0
Sharding-Sphere-SQL                      : Rule Type: master-slave
Sharding-Sphere-SQL                      : SQL: select * from stores limit 5 ::: DataSources: slave1
Sharding-Sphere-SQL                      : Rule Type: master-slave
Sharding-Sphere-SQL                      : SQL: insert into stores (name, description) VALUES ("name103", "description103"); ::: DataSources: master
Sharding-Sphere-SQL                      : Rule Type: master-slave
Sharding-Sphere-SQL                      : SQL: select * from stores limit 5 ::: DataSources: master
           

    代码如下:

package com.example.demo.shardingsphere.raw.jdbc;

import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.transaction.annotation.Transactional;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;

@Slf4j
@SpringBootTest
@ExtendWith(SpringExtension.class)
public class ShardingMasterSlaveDataSourceTest {

    @Autowired
    ShardingMasterSlaveDataSource shardingMasterSlaveDataSource;

    /**
     * 运行后从日志可以看出主从之间的切换和从库负载均衡
     */
    @Test @Transactional
    public void test() throws SQLException {
        DataSource dataSource = shardingMasterSlaveDataSource.createDataSource();
        log.info("ShardingMasterSlaveDataSource info::" + dataSource.getConnection().getMetaData().getURL());

        Connection conn = dataSource.getConnection();
        Statement statement = conn.createStatement();

        String sql = "select * from stores limit 5";
        statement.execute(sql);
        statement.execute(sql);

        sql = "insert into stores (name, description) VALUES (\"name103\", \"description103\");";
        statement.execute(sql);

        sql = "select * from stores limit 5";
        statement.execute(sql);
    }
}