前言
Apache ShardingSphere 是一款分布式的数据库生态系统, 可以将任意数据库转换为分布式数据库,并通过数据分片、弹性伸缩、加密等能力对原有数据库进行增强(引自官网)。
一、配置测试环境
1.安装docker
该操作不做过多赘述,博主有一篇博客是专门用于介绍如何部署docker环境的,链接放下面
docker安装教程
2.安装mysql(基于docker)
2.1 拉取mysql镜像
博主下载的是8.0.28版本的mysql,如果需要更换版本只需要修改后面的版本号就可以
docker pull mysql:8.0.28
2.2 启动mysql
2.2.1 简单启动
该启动操作,不会在服务器本地记录mysql日志、也无法实现数据本地持久化,但是也算是启动成功了
docker run -p 本地映射端口:3306 -e MYSQL_ROOT_PASSWORD=密码 -d mysql:8.0.28
2.2.2 基于配置启动
想实现本地数据持久化可以使用下面的启动方式
拷贝一份mysql配置文件到服务器本地,配置根据个人需求自行修改
docker cp e407810d1149:/etc/mysql/my.cnf /software/mysql-master
e407810d1149 启动的mysql容器ID
/software/mysql-master 服务器本地配置文件存储路径
启动mysql容器
docker run -d \
-p 本地映射端口:3306 \
--privileged=true \
-v mysql日志本地存储路径:/var/log/mysql \
-v mysql数据持久化路径:/var/lib/mysql \
-v mysql配置文件本地存储路径:/etc/mysql/conf.d \
--name 自定义该启动容器名称 \
-e MYSQL_ROOT_PASSWORD=root账号连接数据库密码 \
mysql:8.0.28
本地映射端口号最好不要使用3306这种常用端口,因为博主的云服务器因为开放了该端口被攻击过
2.3 搭建mysql主从服务
因为只有一台服务器的缘故,所以主从服务都在一台服务器上搭建了(如果条件允许也可以在多个服务器上搭建环境)
因为使用了docker的缘故这一步就变得非常简单了,将上序步骤2.2.2执行多次就可以搭建多个mysql服务了,需要改动的就是 本地映射端口 和 自定义的容器名称,类似于下图:
2.3.1 注意事项
每个mysql服务都是有一个单独的配置、数据、日志存储路径的,这一点在启动mysql服务时也要修改
每个mysql服务的 server-id 这一项配置是不相同的,不然启动主从配置时会不生效,该配置项在my.cnf中配置
二、配置mysql多服务的主从同步
1.主服务器操作
1.1 创建一个用户给从服务做数据拷贝操作
#创建 slave 用户
create user 'slave'@'%';
#为slave用户 设置密码
alter user 'slave'@'%' IDENTIFIED WITH mysql_native_password by '自定义密码';
# 赋予复制权限
GRANT replication SLAVE ON *.* TO 'slave'@'%';
# 刷新权限
FLUSH PRIVILEGES;
1.2获取binlog信息
# 用于获取MySQL主服务器(Master)的二进制日志(Binlog)复制状态信息
show master status;
2.从服务器操作
2.1 进行主从复制配置
change master to
master_host = '服务器IP',
master_user = 'slave',
master_password = '自定义slave密码',
master_port = 主服务端口,
master_log_file = 'Binlog File字段信息',
master_log_pos = Binlog Position字段信息;
2.2 启动从服务器复制功能
start slave;
2.3 查看启动状态
show slave status;
此处重点关注 Slave_IO_Running、Slave_SQL_Running这两个参数,两者都为YES表示启动成功,两者任意一个部位YES都是启动失败
如何查看启动失败的原因也很简单,如果启动失败该结果的以下四个字段会记录错误信息,将其复制到网上一查就清楚了
2.4主从复制功能重启、停止
#停止主从复制
stop slave;
#重启主从复制
reset master;
2.5查看服务serverID
show variables like 'server_id';
如果有多个从服务需要开启主从操作,将上面的命令在另外的从服务器中执行就行
3.测试配置结果
在master服务中进行创建数据库、表、插入数据、删除数据操作 查看slave服务是否也是进行了相同的操作,如果都是同步执行,那就是已经成功开启了主从同步了
三、使用 shardingsphere-jdbc 操作数据库进行读写分离
1.引入pom依赖
创建一个springboot应用程序,引入以下依赖
博主测试使用的shardingsphere-jdbc-core-spring-boot-starter版本为5.1.2,看了下官方文档,5.1.2以后的配置可能会跟此版本有区别,最好版本同步
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--shardingsphere-jdbc 主要依赖-->
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
<version>5.1.2</version>
</dependency>
<!-- mysql驱动-->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<!--mybatis-plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
2.配置shardingsphere-jdbc
以下配置项详情可以参考官网
shardingsphere-jdbc5.1.2官方文档
spring:
application:
name: sharding-jdbc-demo
shardingsphere:
# 内存模式(在5.1.2之后的版本貌似没有这个模式)
mode:
type: Memory
# 多数据源配置
datasource:
# 名字随便定义
names: master,slave1,slave2
master:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name : com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://服务器IP:服务端口/库名称?characterEncoding=utf8&useSSL=true&serverTimezone=GMT%2B8
username: root
password: 自定义密码
slave1:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://服务器IP:服务端口/库名称?characterEncoding=utf8&useSSL=true&serverTimezone=GMT%2B8
username: root
password: 自定义密码
slave2:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://服务器IP:服务端口/库名称?characterEncoding=utf8&useSSL=true&serverTimezone=GMT%2B8
username: root
password: 自定义密码
# 配置 读写分离
rules:
readwrite-splitting:
data-sources:
# myds 这个名字是可以自定义的 master,slave1,slave2 三个数据源共同构成了 myds 这个逻辑数据源
myds:
# 类型为 Static,Dynamic
type: Static
props:
# 写 数据源
write-data-source-name: master
# 读 数据源 多个用逗号隔开
read-data-source-names: slave1,slave2
# 负载均衡算法名称(自定义)
load-balancer-name: alg_weight
# 负载均衡算法类型
load-balancers:
# 轮询算法
alg_round:
type: ROUND_ROBIN
# 随机访问算法
alg_random:
type: RANDOM
# 权重访问算法(使用中的读库都必须配置权重)
alg_weight:
type: WEIGHT
props:
slave1: 1
slave2: 2
props:
# 打印sql
sql-show: true
配置完后 执行主程序 启动试试,如果正常启动就表示配置正确,如果启动失败肯定是哪个参数配置错误了,最好的解决办法就是参考官方文档,里面说明都很详细
3.测试是否实现读写分离
第二步的yml文件 配置了 master 服务为写操作 slave1,slave2 为读操作,我们来测试是否实现读写分离
1.创建实体类
@Data
@TableName("t_user")
public class User {
@TableId(type= IdType.AUTO)
private Long id;
private String username;
}
2.创建mapper层
@Mapper
public interface UserMapper extends BaseMapper<User> {
}
3.开始测试
创建测试方法执行 新增、查询 操作
@SpringBootTest
public class ReadWriteTest {
@Autowired
private UserMapper userMapper;
/**
* 写数据测试
*/
@Test
public void test1(){
User user = new User();
user.setUsername("晨曦");
userMapper.insert(user);
}
@Test
public void test2(){
List<User> users = userMapper.selectList(null);
}
@Transactional
@Test
public void test3(){
User user = new User();
user.setUsername("李四");
userMapper.insert(user);
List<User> users = userMapper.selectList(null);
}
}
test1执行的打印结果:
该结果表示实际执行 sql 该添加数据的操作在master服务中执行了,此时在开启主从同步后,其实slave服务也复制了该数据,可以在数据库中进行查看
test2执行的打印结果:
该结果表示实际执行 sql 表示查询的操作是在slave1 从服务进行查询的,这两个示例表示已经是实现了 读写分离操作的
test3执行的打印结果:
test3展示的是在执行事务操作时的情况,在分库的情况下执行事务操作,是不会进行多个库操作的,其操作都是在master数据库进行的
总结
本篇文章主要介绍了分库情况下多服务的主从服务如何进行配置,springboot程序中shardingSphere-jdbc是如何进行的读写分离操作,希望对各位小伙伴有帮助。