Sharding-JDBC 实现读写分离

Sharding-JDBC 是 apache 旗下的 ShardingSphere 中的一款产品,轻量,引入 jar 即可完成读写分离的需求,可以理解为增强版的 JDBC,现在被使用的较多。

搭建项目

maven 依赖的库

<!-- 当前最新版 sharding-jdbc -->
<dependency>
  <groupId>org.apache.shardingsphere</groupId>
  <artifactId>sharding-jdbc-core</artifactId>
  <version>4.1.1</version>
</dependency>
<!-- 结合官方文档使用了 HikariCP 数据库连接池 -->
<dependency>
  <groupId>com.zaxxer</groupId>
  <artifactId>HikariCP</artifactId>
  <version>3.4.5</version>
</dependency>
<!-- MySQL 8.0.21 驱动 -->
<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>8.0.21</version>
</dependency>

 

获取数据源的工具类

package constxiong;

import com.zaxxer.hikari.HikariDataSource;

/**
 * 获取 DataSource 工具类,使用了 Hikari 数据库连接池
 */
import javax.sql.DataSource;

public final class DataSourceUtil {

    private static final int PORT = 3306;

    /**
     * 通过 Hikari 数据库连接池创建 DataSource
     * @param ip
     * @param username
     * @param password
     * @param dataSourceName
     * @return
     */
    public static DataSource createDataSource(String ip, String username, String password, String dataSourceName) {
        HikariDataSource result = new HikariDataSource();
        result.setDriverClassName(com.mysql.jdbc.Driver.class.getName());
        result.setJdbcUrl(String.format("jdbc:mysql://%s:%s/%s?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8", ip, PORT, dataSourceName));
        result.setUsername(username);
        result.setPassword(password);
        return result;
    }
}

 

测试 Sharding-JDBC 读写分离

主库:172.31.32.184

从库:172.31.32.234

观察通过 Sharding-JDBC 获取的 DataSource 是否会自动写入到主库,从库是否主动同步,从库同步数据的延迟时间


测试代码

package constxiong;

import org.apache.shardingsphere.api.config.masterslave.MasterSlaveRuleConfiguration;
import org.apache.shardingsphere.shardingjdbc.api.MasterSlaveDataSourceFactory;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.time.LocalTime;
import java.util.*;

/**
 * 测试 ShardingSphere 读写分离
 * 主库:172.31.32.184
 * 从库:172.31.32.234
 *
 * 观察通过 ShardingSphere 获取的 DataSource 是否会自动写入到主库,从库是否主动同步,从库同步数据的延迟时间
 */
public class Test {

    //主库 DataSource
    private static DataSource dsSlave = DataSourceUtil.createDataSource("172.31.32.234", "root", "constxiong@123", "constxiong");
    //从库 DataSource
    private static DataSource dsMaster = DataSourceUtil.createDataSource("172.31.32.184", "root", "constxiong@123", "constxiong");

    public static void main(String[] args) throws SQLException {
        //启动线程打印主库与从库当前 cuser 数据量与时间,观察从库同步数据延迟
        printMasterAndSlaveData();

        //从 ShardingSphere 获取 DataSource,出入数据,观察插入数据的库是否为主库
        DataSource ds = getMasterSlaveDataSource();
        Connection conn = ds.getConnection();
        Statement stt = conn.createStatement();
        stt.execute("insert into cuser values(2, 'fj')");
    }

    /**
     * 启动线程打印,两个主从库 cuser 表的信息、数据量、当前时间
     * @throws SQLException
     */
    private static void printMasterAndSlaveData() throws SQLException {
        Connection masterConn = dsMaster.getConnection();
        Connection slaveConn = dsSlave.getConnection();
        new Thread(() -> {
            while (true) {
                try {
                    System.out.println("------master------" + LocalTime.now());
                    print(masterConn);
                    System.out.println("------slave------" + LocalTime.now());
                    print(slaveConn);
                } catch (SQLException e) {
                }
            }
        }).start();
    }

    private static void print(Connection conn) throws SQLException {
        Statement statement = conn.createStatement();
        statement.execute("select * from cuser");
        ResultSet rs = statement.getResultSet();
        int count = 0;
        while (rs.next()) {
            int id = rs.getInt("id");
            String name = rs.getString("name");
            System.out.println(id + "-" + name);
            count++;
        }
        System.out.println("total: " + count);
    }

    /**
     * 设置 ShardingSphere 的主从库
     * @return
     * @throws SQLException
     */
    private static DataSource getMasterSlaveDataSource() throws SQLException {
        MasterSlaveRuleConfiguration masterSlaveRuleConfig = new MasterSlaveRuleConfiguration("ds_master_slave", "ds_master", Arrays.asList("ds_slave"));
        return MasterSlaveDataSourceFactory.createDataSource(createDataSourceMap(), masterSlaveRuleConfig, new Properties());
    }

    /**
     * 用 主从库的 DataSource 构造 map
     * @return
     */
    private static Map<String, DataSource> createDataSourceMap() {
        Map<String, DataSource> result = new HashMap<>();
        result.put("ds_master", dsMaster);
        result.put("ds_slave", dsSlave);
        return result;
    }
}

 

分析延迟信息

数据默认配置的情况,在内网从库同步的时间延迟,在 200ms 左右,当然这个统计是不精确的,只是看个大概情况,理论值应该是可以做毫秒级

 

参考文档:

 

代码上传至:

 

 


【Java学习资源】整理推荐

 

 


【Java面试题与答案】整理推荐

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值