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>
获取数据源的工具类
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.101
从库:172.31.32.102
观察通过 Sharding-JDBC 获取的 DataSource 是否会自动写入到主库,从库是否主动同步,从库同步数据的延迟时间
测试代码
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.101
* 从库:172.31.32.102
*
* 观察通过 ShardingSphere 获取的 DataSource 是否会自动写入到主库,从库是否主动同步,从库同步数据的延迟时间
*/
public class Test {
//主库 DataSource
private static DataSource dsSlave = DataSourceUtil.createDataSource("172.31.32.102", "root", "password@appblog.cn", "appblog");
//从库 DataSource
private static DataSource dsMaster = DataSourceUtil.createDataSource("172.31.32.101", "root", "password@appblog.cn", "appblog");
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(1, 'test')");
}
/**
* 启动线程打印,两个主从库 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 左右,当然这个统计是不精确的,只是看个大概情况,理论值应该是可以做毫秒级。
版权声明:
作者:Joe.Ye
链接:https://www.appblog.cn/index.php/2023/03/26/sharding-jdbc-implementation-for-read-write-separation/
来源:APP全栈技术分享
文章版权归作者所有,未经允许请勿转载。
THE END
0
二维码
打赏
海报
Sharding-JDBC 实现读写分离
Sharding-JDBC 是 Apache 旗下的 ShardingSphere 中的一款产品,轻量,引入 jar 即可完成读写分离的需求,可以理解为增强版的 JDBC,现在被使用的较多。
maven……
文章目录
关闭
共有 0 条评论