飞行的蜗牛

vuePress-theme-reco 极客学长    2013 - 2025
飞行的蜗牛 飞行的蜗牛

Choose mode

  • dark
  • auto
  • light
首页
分类
  • 技术杂谈
  • Database
  • Docker
  • PHP
  • 随笔杂谈
  • 前端开发
  • FunnyTools
  • Jekyll
  • 读书笔记
  • Java
  • SpringBoot
  • 区块链技术
  • IPFS
  • C/C++
  • Filecoin
  • Golang
  • Sharding-JDBC
  • 分布式存储
  • Lotus-源码系列
  • Lotus
  • 框架源码系列
  • Spring-源码系列
  • AI
  • ChatGPT
  • Stable Diffusion
  • DeepSeek-R1
  • DeepSeek-V3
标签
时间抽
关于作者
开源项目
GeekAI (opens new window)
author-avatar

极客学长

154

文章

151

标签

首页
分类
  • 技术杂谈
  • Database
  • Docker
  • PHP
  • 随笔杂谈
  • 前端开发
  • FunnyTools
  • Jekyll
  • 读书笔记
  • Java
  • SpringBoot
  • 区块链技术
  • IPFS
  • C/C++
  • Filecoin
  • Golang
  • Sharding-JDBC
  • 分布式存储
  • Lotus-源码系列
  • Lotus
  • 框架源码系列
  • Spring-源码系列
  • AI
  • ChatGPT
  • Stable Diffusion
  • DeepSeek-R1
  • DeepSeek-V3
标签
时间抽
关于作者
开源项目
GeekAI (opens new window)
  • Sharding-JDBC 系列 02 - 读写分离

Sharding-JDBC 系列 02 - 读写分离

vuePress-theme-reco 极客学长    2013 - 2025

Sharding-JDBC 系列 02 - 读写分离


极客学长 2019-07-29 0 sharding-jdbc 读写分离

上文我们讲述了如何使用 Sharding-JDBC 分库分表

本文我们讲述如何使用 Sharding-JDBC 实现读写分离。为了节省时间,我们项目结构仍然沿用上文的,只需要增加读写分离的配置就好了。

# 配置 MySQL 读写分离

请参考我的另一篇博客 使用 docker 搭建 MySQL 主从同步/读写分离。这里就不赘述了。

# 创建数据表

分别在 master 和 slave 节点分别执行下面的 SQL

CREATE DATABASE demo_ds CHARSET=utf8;
use demo_ds;
DROP TABLE IF EXISTS `t_user_0`;
CREATE TABLE `t_user_0` (
  `user_id` bigint(20) AUTO_INCREMENT,
  `username` varchar(30) NOT NULL,
  `password` varchar(30) DEFAULT NULL,
  PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

DROP TABLE IF EXISTS `t_user_1`;
CREATE TABLE `t_user_1` (
  `user_id` bigint(20) AUTO_INCREMENT,
  `username` varchar(30) NOT NULL,
  `password` varchar(30) DEFAULT NULL,
  PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

# 配置 Properties

这里我们只需要修改 application.properties,其他的项目文件,比如 Mapper, Model, Service 等我们都沿用上个项目的。

# 所有数据源列表
sharding.jdbc.datasource.names=ds-master,ds-slave-0

# 主数据源
sharding.jdbc.datasource.ds-master.type=com.alibaba.druid.pool.DruidDataSource
sharding.jdbc.datasource.ds-master.driver-class-name=com.mysql.jdbc.Driver
sharding.jdbc.datasource.ds-master.url=jdbc:mysql://localhost:3307/demo_ds
sharding.jdbc.datasource.ds-master.username=root
sharding.jdbc.datasource.ds-master.password=123456

# 从数据源,这里我是用 docker 在本地创建了2个 MySQL 服务容器,数据库名称一样,方便配置 MySQL 主从复制,端口不一样
sharding.jdbc.datasource.ds-slave-0.type=com.alibaba.druid.pool.DruidDataSource
sharding.jdbc.datasource.ds-slave-0.driver-class-name=com.mysql.jdbc.Driver
sharding.jdbc.datasource.ds-slave-0.url=jdbc:mysql://localhost:3308/demo_ds
sharding.jdbc.datasource.ds-slave-0.username=root
sharding.jdbc.datasource.ds-slave-0.password=123456

# 读写分离设置
sharding.jdbc.config.sharding.master-slave-rules.ds0.master-data-source-name=ds-master
sharding.jdbc.config.sharding.master-slave-rules.ds0.slave-data-source-names=ds-slave-0


# 分表配置
#actual-data-nodes:真实数据节点,由数据源名 + 表名组成,以小数点分隔。多个表以逗号分隔,支持inline表达式
sharding.jdbc.config.sharding.tables.t_user.actual-data-nodes=ds0.t_user_${0..1}
# 分表的字段配置
sharding.jdbc.config.sharding.tables.t_user.table-strategy.inline.sharding-column=user_id
# 分表的算法表达式(取模 , HASH , 分块等)
sharding.jdbc.config.sharding.tables.t_user.table-strategy.inline.algorithm-expression=t_user_${user_id.longValue() \
  % 2}
# 配置自动生成主键
sharding.jdbc.config.sharding.tables.t_user.key-generator-column-name=user_id

# open debug mode for mybatis,print SQL in console
logging.level.org.rockyang.shardingjdbc.common.mapper=DEBUG
logging.level.org.springframework=INFO
mybatis.configuration.cache-enabled=false

# Application

@SpringBootApplication(scanBasePackages={
		// 这里用的是上个项目的 mapper 和 service, 所以需要把扫描路径加入
		"org.rockyang.shardingjdbc.common",
		"org.rockyang.shardingjdbc.rw"
})
@MapperScan("org.rockyang.shardingjdbc.common.mapper")
public class MasterSlaveApplication {

	public static void main(String[] args) {
		SpringApplication.run(MasterSlaveApplication.class, args);
	}

}

这里因为项目进行了重构,我把通用的 Mapper, Model, Service 都抽出来放到 common 模块了。具体架构请到后面看完整的项目源码。

# 执行单元测试

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

	private static Logger logger = LoggerFactory.getLogger(MasterSlaveTest.class);

	@Autowired
	private UserService userService;

	@Test
	public void testAdd()
	{
		String username = StringUtil.generateRandomString(20);
		String password = StringUtil.generateRandomString(20);
		User user = new User(username, password);
		userService.add(user);
		logger.info("userId: {}", user.getUserId());
	}

	@Test
	public void testAddBatch()
	{
		String username;
		String password;
		for (int i = 0; i < 100; i++) {
			username = StringUtil.generateRandomString(20);
			password = StringUtil.generateRandomString(20);
			User user = new User(username, password);
			userService.add(user);
			logger.info("userId: {}", user.getUserId());
		}
	}

	@Test
	public void testSelect()
	{
		List<User> users = userService.selectAll();
		logger.info("Total records: {}", users.size());
		for (User user : users) {
			logger.info("{}", user);
		}
	}
}

# 验证测试结果

  • 执行 testAddBatch() 单元测试,往 master 节点插入 100 条数据,然后 slave 节点是否同步了数据
  • 在 slave 节点删除一条数据,然后执行 testSelect() 单元测试,如果查询出来的数据是 99 条,则说明是从 slave 节点读取的数据。

# 项目源码链接

sharding-jdbc-spring-boot-demo (opens new window)

# 参考链接

  • https://shardingsphere.apache.org/document/current/cn/manual/sharding-jdbc/usage/read-write-splitting/

本站博文如非注明转载则均属作者原创文章,引用或转载无需申请版权或者注明出处,如需联系作者请加微信: geekmaster01

Sharding-JDBC 系列 03 - 自定义分片算法 使用 docker 搭建 Redis 主从同步