| 机器名称 | IP | 角色 | 权限 |
|---|---|---|---|
| Mysql_Master1 | 172.16.94.5 | 数据库 Master | 可读写、主库 |
| Mysql_Slave1 | 172.16.94.6 | 数据库 Slave | 只读、从库 |
| Mysql_Slave2 | 172.16.94.10 | 数据库 Slave | 只读、从库 |
| Mysql_Master11 | 172.16.94.17 | 数据库 Master11 | 可读写、主库 |
| Mysql_Slave11 | 172.16.94.18 | 数据库 Slave11 | 只读、从库 |
| Mysql_Slave22 | 172.16.94.19 | 数据库 Slave22 | 只读、从库 |
MySQL 主从搭建 一主二从
主库配置/etc/my.cnf
#bin_log 配置log_bin=mysql-binserver-id=1sync-binlog=1binlog-ignore-db=information_schemabinlog-ignore-db=performance_schemabinlog-ignore-db=sys#relay_log 配置relay_log=mysql-relay-binlog_slave_updates=1relay_log_purge=0
两台从库配置/etc/my.cnf
#bin_log 配置log_bin=mysql-bin#服务器 ID,从库 2、3server-id=2sync-binlog=1binlog-ignore-db=information_schemabinlog-ignore-db=mysqlbinlog-ignore-db=performance_schema#relay_log 配置relay_log=mysql-relay-binlog_slave_updates=1relay_log_purge=0read_only=1
三台分别重启服务
systemctl restart mysqld
主库开启权限
#进入mysqlgrant replication slave on *.* to 'root'@'%' identified by 'root';grant all privileges on *.* to 'root'@'%' identified by 'root';flush privileges;grant replication slave on *.* to 'mha'@'%' identified by '123123';grant all privileges on *.* to 'mha'@'%' identified by '123123';flush privileges;
两台从库建立主从关系
#查看是否以前有配置信息,若有则去除掉show slave status;#stop slave;#reset slave all;#在主库查看binlog状态#show master status \G;#从库设置主库信息change master to master_host='172.16.94.5',master_port=3306,master_user='root',master_password='root',master_log_file='mysql-bin.000014',master_log_pos=154;#开启从库start slave;#再次查看从库配置信息show slave status \G;
分别复制主库和两个从库
虚拟机直接克隆

修改主库 2 配置/etc/my.cnf
server-id=11
修改从库 11、22 配置/etc/my.cnf
vim /etc/my.cnfserver-id=12server-id=13
查找下 auto.cnf 文件的位置,全部修改
find / -name "auto.cnf"vim /var/lib/mysql/auto.cnf[auto]server-uuid=356fc1ff-e339-11eb-bbea-000c29c18311
查看主库 22 的状态
mysql> show master status \G;*************************** 1. row ***************************File: mysql-bin.000015Position: 154Binlog_Do_DB:Binlog_Ignore_DB: information_schema,performance_schema,sysExecuted_Gtid_Set:1 row in set (0.00 sec)
修改从库 22 和从库 33 的主库
mysql> stop slave;Query OK, 0 rows affected (0.01 sec)mysql> reset slave all;Query OK, 0 rows affected (0.01 sec)mysql> change master to master_host='172.16.94.17',master_port=3306,master_user='root',master_password='root',-> master_log_file='mysql-bin.000015',master_log_pos=154;Query OK, 0 rows affected, 2 warnings (0.01 sec)mysql> start slave;Query OK, 0 rows affected (0.01 sec)mysql> show slave status \G;*************************** 1. row ***************************Slave_IO_State: Waiting for master to send eventMaster_Host: 172.16.94.17Master_User: rootMaster_Port: 3306Connect_Retry: 60Master_Log_File: mysql-bin.000015Read_Master_Log_Pos: 154Relay_Log_File: mysql-relay2-bin.000002Relay_Log_Pos: 320Relay_Master_Log_File: mysql-bin.000015Slave_IO_Running: YesSlave_SQL_Running: Yes1 row in set (0.00 sec)
重启下这三台服务
systemctl restart mysqld
初始化数据
主库分别创建 lane3、lane5 和 c_order 表
➜ ~ mysql -uroot -prootmysql> create database lane5;Query OK, 1 row affected (0.00 sec)mysql> use lane5;Database changedmysql> CREATE TABLE `c_order` (-> `id` BIGINT ( 20 ) NOT NULL AUTO_INCREMENT,-> `is_del` bit ( 1 ) NOT NULL DEFAULT 0 COMMENT '是否被删除',-> `user_id` INT ( 11 ) NOT NULL COMMENT '⽤户id',-> `company_id` INT ( 11 ) NOT NULL COMMENT '公司id',-> `publish_user_id` INT ( 11 ) NOT NULL COMMENT 'B端⽤户id',-> `position_id` INT ( 11 ) NOT NULL COMMENT '职位ID',-> `resume_type` INT ( 2 ) NOT NULL DEFAULT 0 COMMENT '简历类型:0附件 1在线',-> `status` VARCHAR ( 256 ) NOT NULL COMMENT '投递状态 投递状态 WAIT-待处理 AUTO_FILTER-⾃动过滤 PREPARE_CONTACT-待沟通 REFUSE-拒绝 ARRANGE_INTERVIEW-通知⾯试',-> `create_time` datetime NOT NULL COMMENT '创建时间',-> `update_time` datetime NOT NULL COMMENT '处理时间',-> PRIMARY KEY ( `id` ),-> KEY `index_userId_positionId` ( `user_id`, `position_id` ),-> KEY `idx_userId_operateTime` ( `user_id`, `update_time` )-> ) ENGINE = INNODB DEFAULT CHARSET = utf8mb4;Query OK, 0 rows affected (0.01 sec)mysql>
查看第二组从库是否 有 lane5 和 c_order 表
➜ ~ mysql -uroot -prootmysql> show databases;+--------------------+| Database |+--------------------+| information_schema || lane1 || lane2 || lane5 || lanebin || mysql || performance_schema || sys |+--------------------+8 rows in set (0.01 sec)mysql> use lane5mysql> show tables;+-----------------+| Tables_in_lane5 |+-----------------+| c_order |+-----------------+1 row in set (0.00 sec)mysql>
查看第一组从库是否 有 lane3 和 c_order 表
mysql> use lane3Reading table information for completion of table and column namesYou can turn off this feature to get a quicker startup with -ADatabase changedmysql> show tables;+-----------------+| Tables_in_lane3 |+-----------------+| c_order |+-----------------+1 row in set (0.00 sec)mysql>
开始创建项目
创建 maven 项目 mysql-work
添加依赖
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.galaxy</groupId><artifactId>mysql-work</artifactId><version>1.0-SNAPSHOT</version><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.2.9.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><description>Demo project for Spring Boot</description><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.compile.sourceEncoding>UTF-8</project.compile.sourceEncoding><shardingsphere.version>4.1.0</shardingsphere.version><springboot.version>2.2.9.RELEASE</springboot.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId><version>${springboot.version}</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId><version>${springboot.version}</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId><version>2.1.6.RELEASE</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><version>${springboot.version}</version><scope>test</scope></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.48</version></dependency><dependency><groupId>org.apache.shardingsphere</groupId><artifactId>sharding-jdbc-spring-boot-starter</artifactId><version>${shardingsphere.version}</version></dependency><dependency><groupId>org.apache.shardingsphere</groupId><artifactId>sharding-transaction-xa-core</artifactId><version>${shardingsphere.version}</version></dependency></dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.8.1</version><configuration><source>11</source><target>11</target><testSource>11</testSource><testTarget>11</testTarget></configuration></plugin></plugins></build></project>
entity
package com.galaxy.entity;import javax.persistence.*;import java.util.Date;/*** @author lane* @date 2021年07月27日 下午7:12*/@Entity@Table(name = "c_order")public class Order {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@Column(name = "is_del")private Boolean del;@Column(name = "user_id")private Integer userId;@Column(name = "company_id")private Integer companyId;@Column(name = "publish_user_id")private Integer publishUserId;@Column(name = "position_id")private Integer positionId;@Column(name = "resume_type")private Integer resumeType;@Column(name = "status")private String status;@Column(name = "create_time")private Date createTime;@Column(name = "update_time")private Date updateTime;public Long getId() {return id;}public void setId(Long id) {this.id = id;}public Boolean getDel() {return del;}public void setDel(Boolean del) {this.del = del;}public Integer getUserId() {return userId;}public void setUserId(Integer userId) {this.userId = userId;}public Integer getCompanyId() {return companyId;}public void setCompanyId(Integer companyId) {this.companyId = companyId;}public Integer getPublishUserId() {return publishUserId;}public void setPublishUserId(Integer publishUserId) {this.publishUserId = publishUserId;}public Integer getPositionId() {return positionId;}public void setPositionId(Integer positionId) {this.positionId = positionId;}public Integer getResumeType() {return resumeType;}public void setResumeType(Integer resumeType) {this.resumeType = resumeType;}public String getStatus() {return status;}public void setStatus(String status) {this.status = status;}public Date getCreateTime() {return createTime;}public void setCreateTime(Date createTime) {this.createTime = createTime;}public Date getUpdateTime() {return updateTime;}public void setUpdateTime(Date updateTime) {this.updateTime = updateTime;}@Overridepublic String toString() {return "Order{" +"id=" + id +", del=" + del +", userId=" + userId +", companyId=" + companyId +", publishUserId=" + publishUserId +", positionId=" + positionId +", resumeType=" + resumeType +", status='" + status + '\'' +", createTime=" + createTime +", updateTime=" + updateTime +'}';}}
repository
package com.galaxy.repository;import com.galaxy.entity.Order;import org.springframework.data.jpa.repository.JpaRepository;/*** @author lane* @date 2021年07月27日 下午7:14*/public interface OrderRepository extends JpaRepository<Order,Long> {}
application.properties
spring.shardingsphere.datasource.names=master-0,slave-1,slave-2,master-1,slave-3,slave-4spring.shardingsphere.props.sql.show=truespring.shardingsphere.datasource.master-0.type=com.zaxxer.hikari.HikariDataSourcespring.shardingsphere.datasource.master-0.driver-class-name=com.mysql.jdbc.Driverspring.shardingsphere.datasource.master-0.jdbc-url=jdbc:mysql://172.16.94.5:3306/lane3?useUnicode=true&useSSL=falsespring.shardingsphere.datasource.master-0.username=rootspring.shardingsphere.datasource.master-0.password=rootspring.shardingsphere.datasource.slave-1.type=com.zaxxer.hikari.HikariDataSourcespring.shardingsphere.datasource.slave-1.driver-class-name=com.mysql.jdbc.Driverspring.shardingsphere.datasource.slave-1.jdbc-url=jdbc:mysql://172.16.94.6:3306/lane3?useUnicode=true&useSSL=falsespring.shardingsphere.datasource.slave-1.username=rootspring.shardingsphere.datasource.slave-1.password=rootspring.shardingsphere.datasource.slave-2.type=com.zaxxer.hikari.HikariDataSourcespring.shardingsphere.datasource.slave-2.driver-class-name=com.mysql.jdbc.Driverspring.shardingsphere.datasource.slave-2.jdbc-url=jdbc:mysql://172.16.94.10:3306/lane3?useUnicode=true&useSSL=falsespring.shardingsphere.datasource.slave-2.username=rootspring.shardingsphere.datasource.slave-2.password=rootspring.shardingsphere.datasource.master-1.type=com.zaxxer.hikari.HikariDataSourcespring.shardingsphere.datasource.master-1.driver-class-name=com.mysql.jdbc.Driverspring.shardingsphere.datasource.master-1.jdbc-url=jdbc:mysql://172.16.94.17:3306/lane5?useUnicode=true&useSSL=falsespring.shardingsphere.datasource.master-1.username=rootspring.shardingsphere.datasource.master-1.password=rootspring.shardingsphere.datasource.slave-3.type=com.zaxxer.hikari.HikariDataSourcespring.shardingsphere.datasource.slave-3.driver-class-name=com.mysql.jdbc.Driverspring.shardingsphere.datasource.slave-3.jdbc-url=jdbc:mysql://172.16.94.18:3306/lane5?useUnicode=true&useSSL=falsespring.shardingsphere.datasource.slave-3.username=rootspring.shardingsphere.datasource.slave-3.password=rootspring.shardingsphere.datasource.slave-4.type=com.zaxxer.hikari.HikariDataSourcespring.shardingsphere.datasource.slave-4.driver-class-name=com.mysql.jdbc.Driverspring.shardingsphere.datasource.slave-4.jdbc-url=jdbc:mysql://172.16.94.19:3306/lane5?useUnicode=true&useSSL=falsespring.shardingsphere.datasource.slave-4.username=rootspring.shardingsphere.datasource.slave-4.password=rootspring.shardingsphere.sharding.tables.c_order.database-strategy.inline.sharding-column=user_idspring.shardingsphere.sharding.tables.c_order.database-strategy.inline.algorithm-expression=master-$->{user_id % 2}spring.shardingsphere.sharding.tables.c_order.actual-data-nodes=master-$->{0..1}.c_orderspring.shardingsphere.sharding.tables.c_order.key-generator.column=idspring.shardingsphere.sharding.tables.c_order.key-generator.type=SNOWFLAKEspring.shardingsphere.sharding.master-slave-rules.master-0.master-data-source-name=master-0spring.shardingsphere.sharding.master-slave-rules.master-0.slave-data-source-names=slave-1,slave-2#spring.shardingsphere.masterslave.load-balance-algorithm-type=ROUND_ROBINspring.shardingsphere.sharding.master-slave-rules.master-1.master-data-source-name=master-1spring.shardingsphere.sharding.master-slave-rules.master-1.slave-data-source-names=slave-3,slave-4
test
/*** @author lane* @date 2021年07月27日 下午7:16*/@RunWith(SpringRunner.class)@SpringBootTest(classes = ShardingBootRunApplication.class)public class ShardingTest {@Autowiredprivate OrderRepository orderRepository;@org.junit.Testpublic void test(){for (int idx = 0; idx < 4; ++idx) {Order order = new Order();order.setCompanyId(1);order.setCreateTime(new Date());order.setDel(false);order.setPositionId(1);order.setStatus("WAITING");order.setPublishUserId(1);order.setResumeType(1);order.setUpdateTime(new Date());order.setUserId(idx);orderRepository.save(order);}}@Testpublic void testSlave(){List<Order> all = orderRepository.findAll();System.out.println(all);}}
测试分库分表和主从同步结果
通过 Master1 和 Master11 的查询结果可以看出分库成功
通过 Slave1 和 Slave11 可以看到主从同步 OK
master1
mysql> select * from c_order \G;*************************** 1. row ***************************id: 626865956605394944is_del:user_id: 0company_id: 1publish_user_id: 1position_id: 1resume_type: 1status: WAITINGcreate_time: 2021-07-27 19:41:30update_time: 2021-07-27 19:41:30*************************** 2. row ***************************id: 626865957251317760is_del:user_id: 2company_id: 1publish_user_id: 1position_id: 1resume_type: 1status: WAITINGcreate_time: 2021-07-27 19:41:31update_time: 2021-07-27 19:41:312 rows in set (0.00 sec)
slave1
mysql> use lane3mysql> select * from c_order \G;*************************** 1. row ***************************id: 626865956605394944is_del:user_id: 0company_id: 1publish_user_id: 1position_id: 1resume_type: 1status: WAITINGcreate_time: 2021-07-27 19:41:30update_time: 2021-07-27 19:41:30*************************** 2. row ***************************id: 626865957251317760is_del:user_id: 2company_id: 1publish_user_id: 1position_id: 1resume_type: 1status: WAITINGcreate_time: 2021-07-27 19:41:31update_time: 2021-07-27 19:41:312 rows in set (0.00 sec)
master11
mysql> select * from c_order \G;*************************** 1. row ***************************id: 626865957129682945is_del:user_id: 1company_id: 1publish_user_id: 1position_id: 1resume_type: 1status: WAITINGcreate_time: 2021-07-27 19:41:31update_time: 2021-07-27 19:41:31*************************** 2. row ***************************id: 626865957284872193is_del:user_id: 3company_id: 1publish_user_id: 1position_id: 1resume_type: 1status: WAITINGcreate_time: 2021-07-27 19:41:31update_time: 2021-07-27 19:41:312 rows in set (0.00 sec)
slave11
mysql> use lane5;mysql> select * from c_order\G;*************************** 1. row ***************************id: 626865957129682945is_del:user_id: 1company_id: 1publish_user_id: 1position_id: 1resume_type: 1status: WAITINGcreate_time: 2021-07-27 19:41:31update_time: 2021-07-27 19:41:31*************************** 2. row ***************************id: 626865957284872193is_del:user_id: 3company_id: 1publish_user_id: 1position_id: 1resume_type: 1status: WAITINGcreate_time: 2021-07-27 19:41:31update_time: 2021-07-27 19:41:312 rows in set (0.00 sec)
测试读写分离结果
分别修改下 slave1 和 slave11 中 c_order 表的数据
#slave1update c_order set status ='slave1';#slave11update c_order set status ='slave11';
查看读取的数据,可以看到读取到的是从库中 c_order 的数据,成功实现读写分离
[Order{id=626865956605394944, del=false, userId=0, companyId=1, publishUserId=1, positionId=1, resumeType=1, status='slave1',createTime=2021-07-27 19:41:30.0, updateTime=2021-07-27 19:41:30.0},Order{id=626865957251317760, del=false, userId=2, companyId=1, publishUserId=1, positionId=1, resumeType=1, status='slave1',createTime=2021-07-27 19:41:31.0, updateTime=2021-07-27 19:41:31.0},Order{id=626865957129682945, del=false, userId=1, companyId=1, publishUserId=1, positionId=1, resumeType=1, status='slave11',createTime=2021-07-27 19:41:31.0, updateTime=2021-07-27 19:41:31.0},Order{id=626865957284872193, del=false, userId=3, companyId=1, publishUserId=1, positionId=1, resumeType=1, status='slave11',createTime=2021-07-27 19:41:31.0, updateTime=2021-07-27 19:41:31.0}]2
