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

  1. #bin_log 配置
  2. log_bin=mysql-bin
  3. server-id=1
  4. sync-binlog=1
  5. binlog-ignore-db=information_schema
  6. binlog-ignore-db=performance_schema
  7. binlog-ignore-db=sys
  8. #relay_log 配置
  9. relay_log=mysql-relay-bin
  10. log_slave_updates=1
  11. relay_log_purge=0

两台从库配置/etc/my.cnf

  1. #bin_log 配置
  2. log_bin=mysql-bin
  3. #服务器 ID,从库 2、3
  4. server-id=2
  5. sync-binlog=1
  6. binlog-ignore-db=information_schema
  7. binlog-ignore-db=mysql
  8. binlog-ignore-db=performance_schema
  9. #relay_log 配置
  10. relay_log=mysql-relay-bin
  11. log_slave_updates=1
  12. relay_log_purge=0
  13. read_only=1

三台分别重启服务

  1. systemctl restart mysqld

主库开启权限

  1. #进入mysql
  2. grant replication slave on *.* to 'root'@'%' identified by 'root';
  3. grant all privileges on *.* to 'root'@'%' identified by 'root';
  4. flush privileges;
  5. grant replication slave on *.* to 'mha'@'%' identified by '123123';
  6. grant all privileges on *.* to 'mha'@'%' identified by '123123';
  7. flush privileges;

两台从库建立主从关系

  1. #查看是否以前有配置信息,若有则去除掉
  2. show slave status;
  3. #stop slave;
  4. #reset slave all;
  5. #在主库查看binlog状态
  6. #show master status \G;
  7. #从库设置主库信息
  8. change master to master_host='172.16.94.5',master_port=3306,master_user='root',master_password='root',
  9. master_log_file='mysql-bin.000014',master_log_pos=154;
  10. #开启从库
  11. start slave;
  12. #再次查看从库配置信息
  13. show slave status \G;

分别复制主库和两个从库

虚拟机直接克隆

image.png

修改主库 2 配置/etc/my.cnf

  1. server-id=11

修改从库 11、22 配置/etc/my.cnf

  1. vim /etc/my.cnf
  2. server-id=12
  3. server-id=13

查找下 auto.cnf 文件的位置,全部修改

  1. find / -name "auto.cnf"
  2. vim /var/lib/mysql/auto.cnf
  3. [auto]
  4. server-uuid=356fc1ff-e339-11eb-bbea-000c29c18311

查看主库 22 的状态

  1. mysql> show master status \G;
  2. *************************** 1. row ***************************
  3. File: mysql-bin.000015
  4. Position: 154
  5. Binlog_Do_DB:
  6. Binlog_Ignore_DB: information_schema,performance_schema,sys
  7. Executed_Gtid_Set:
  8. 1 row in set (0.00 sec)

修改从库 22 和从库 33 的主库

  1. mysql> stop slave;
  2. Query OK, 0 rows affected (0.01 sec)
  3. mysql> reset slave all;
  4. Query OK, 0 rows affected (0.01 sec)
  5. mysql> change master to master_host='172.16.94.17',master_port=3306,master_user='root',master_password='root',
  6. -> master_log_file='mysql-bin.000015',master_log_pos=154;
  7. Query OK, 0 rows affected, 2 warnings (0.01 sec)
  8. mysql> start slave;
  9. Query OK, 0 rows affected (0.01 sec)
  10. mysql> show slave status \G;
  11. *************************** 1. row ***************************
  12. Slave_IO_State: Waiting for master to send event
  13. Master_Host: 172.16.94.17
  14. Master_User: root
  15. Master_Port: 3306
  16. Connect_Retry: 60
  17. Master_Log_File: mysql-bin.000015
  18. Read_Master_Log_Pos: 154
  19. Relay_Log_File: mysql-relay2-bin.000002
  20. Relay_Log_Pos: 320
  21. Relay_Master_Log_File: mysql-bin.000015
  22. Slave_IO_Running: Yes
  23. Slave_SQL_Running: Yes
  24. 1 row in set (0.00 sec)

重启下这三台服务

  1. systemctl restart mysqld

初始化数据

主库分别创建 lane3、lane5 和 c_order 表

  1. ~ mysql -uroot -proot
  2. mysql> create database lane5;
  3. Query OK, 1 row affected (0.00 sec)
  4. mysql> use lane5;
  5. Database changed
  6. mysql> CREATE TABLE `c_order` (
  7. -> `id` BIGINT ( 20 ) NOT NULL AUTO_INCREMENT,
  8. -> `is_del` bit ( 1 ) NOT NULL DEFAULT 0 COMMENT '是否被删除',
  9. -> `user_id` INT ( 11 ) NOT NULL COMMENT '⽤户id',
  10. -> `company_id` INT ( 11 ) NOT NULL COMMENT '公司id',
  11. -> `publish_user_id` INT ( 11 ) NOT NULL COMMENT 'B端⽤户id',
  12. -> `position_id` INT ( 11 ) NOT NULL COMMENT '职位ID',
  13. -> `resume_type` INT ( 2 ) NOT NULL DEFAULT 0 COMMENT '简历类型:0附件 1在线',
  14. -> `status` VARCHAR ( 256 ) NOT NULL COMMENT '投递状态 投递状态 WAIT-待处理 AUTO_FILTER-⾃动过滤 PREPARE_CONTACT-待沟通 REFUSE-拒绝 ARRANGE_INTERVIEW-通知⾯试',
  15. -> `create_time` datetime NOT NULL COMMENT '创建时间',
  16. -> `update_time` datetime NOT NULL COMMENT '处理时间',
  17. -> PRIMARY KEY ( `id` ),
  18. -> KEY `index_userId_positionId` ( `user_id`, `position_id` ),
  19. -> KEY `idx_userId_operateTime` ( `user_id`, `update_time` )
  20. -> ) ENGINE = INNODB DEFAULT CHARSET = utf8mb4;
  21. Query OK, 0 rows affected (0.01 sec)
  22. mysql>

查看第二组从库是否 有 lane5 和 c_order 表

  1. ~ mysql -uroot -proot
  2. mysql> show databases;
  3. +--------------------+
  4. | Database |
  5. +--------------------+
  6. | information_schema |
  7. | lane1 |
  8. | lane2 |
  9. | lane5 |
  10. | lanebin |
  11. | mysql |
  12. | performance_schema |
  13. | sys |
  14. +--------------------+
  15. 8 rows in set (0.01 sec)
  16. mysql> use lane5
  17. mysql> show tables;
  18. +-----------------+
  19. | Tables_in_lane5 |
  20. +-----------------+
  21. | c_order |
  22. +-----------------+
  23. 1 row in set (0.00 sec)
  24. mysql>

查看第一组从库是否 有 lane3 和 c_order 表

  1. mysql> use lane3
  2. Reading table information for completion of table and column names
  3. You can turn off this feature to get a quicker startup with -A
  4. Database changed
  5. mysql> show tables;
  6. +-----------------+
  7. | Tables_in_lane3 |
  8. +-----------------+
  9. | c_order |
  10. +-----------------+
  11. 1 row in set (0.00 sec)
  12. mysql>

开始创建项目

创建 maven 项目 mysql-work

添加依赖

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <modelVersion>4.0.0</modelVersion>
  6. <groupId>com.galaxy</groupId>
  7. <artifactId>mysql-work</artifactId>
  8. <version>1.0-SNAPSHOT</version>
  9. <parent>
  10. <groupId>org.springframework.boot</groupId>
  11. <artifactId>spring-boot-starter-parent</artifactId>
  12. <version>2.2.9.RELEASE</version>
  13. <relativePath/> <!-- lookup parent from repository -->
  14. </parent>
  15. <description>Demo project for Spring Boot</description>
  16. <properties>
  17. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  18. <project.compile.sourceEncoding>UTF-8</project.compile.sourceEncoding>
  19. <shardingsphere.version>4.1.0</shardingsphere.version>
  20. <springboot.version>2.2.9.RELEASE</springboot.version>
  21. </properties>
  22. <dependencies>
  23. <dependency>
  24. <groupId>org.springframework.boot</groupId>
  25. <artifactId>spring-boot-starter-jdbc</artifactId>
  26. <version>${springboot.version}</version>
  27. </dependency>
  28. <dependency>
  29. <groupId>org.springframework.boot</groupId>
  30. <artifactId>spring-boot-starter-data-jpa</artifactId>
  31. <version>${springboot.version}</version>
  32. </dependency>
  33. <dependency>
  34. <groupId>org.springframework.boot</groupId>
  35. <artifactId>spring-boot-starter-data-jpa</artifactId>
  36. <version>2.1.6.RELEASE</version>
  37. </dependency>
  38. <dependency>
  39. <groupId>org.springframework.boot</groupId>
  40. <artifactId>spring-boot-starter-test</artifactId>
  41. <version>${springboot.version}</version>
  42. <scope>test</scope>
  43. </dependency>
  44. <dependency>
  45. <groupId>mysql</groupId>
  46. <artifactId>mysql-connector-java</artifactId>
  47. <version>5.1.48</version>
  48. </dependency>
  49. <dependency>
  50. <groupId>org.apache.shardingsphere</groupId>
  51. <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
  52. <version>${shardingsphere.version}</version>
  53. </dependency>
  54. <dependency>
  55. <groupId>org.apache.shardingsphere</groupId>
  56. <artifactId>sharding-transaction-xa-core</artifactId>
  57. <version>${shardingsphere.version}</version>
  58. </dependency>
  59. </dependencies>
  60. <build>
  61. <plugins>
  62. <plugin>
  63. <groupId>org.apache.maven.plugins</groupId>
  64. <artifactId>maven-compiler-plugin</artifactId>
  65. <version>3.8.1</version>
  66. <configuration>
  67. <source>11</source>
  68. <target>11</target>
  69. <testSource>11</testSource>
  70. <testTarget>11</testTarget>
  71. </configuration>
  72. </plugin>
  73. </plugins>
  74. </build>
  75. </project>

entity

  1. package com.galaxy.entity;
  2. import javax.persistence.*;
  3. import java.util.Date;
  4. /**
  5. * @author lane
  6. * @date 2021年07月27日 下午7:12
  7. */
  8. @Entity
  9. @Table(name = "c_order")
  10. public class Order {
  11. @Id
  12. @GeneratedValue(strategy = GenerationType.IDENTITY)
  13. private Long id;
  14. @Column(name = "is_del")
  15. private Boolean del;
  16. @Column(name = "user_id")
  17. private Integer userId;
  18. @Column(name = "company_id")
  19. private Integer companyId;
  20. @Column(name = "publish_user_id")
  21. private Integer publishUserId;
  22. @Column(name = "position_id")
  23. private Integer positionId;
  24. @Column(name = "resume_type")
  25. private Integer resumeType;
  26. @Column(name = "status")
  27. private String status;
  28. @Column(name = "create_time")
  29. private Date createTime;
  30. @Column(name = "update_time")
  31. private Date updateTime;
  32. public Long getId() {
  33. return id;
  34. }
  35. public void setId(Long id) {
  36. this.id = id;
  37. }
  38. public Boolean getDel() {
  39. return del;
  40. }
  41. public void setDel(Boolean del) {
  42. this.del = del;
  43. }
  44. public Integer getUserId() {
  45. return userId;
  46. }
  47. public void setUserId(Integer userId) {
  48. this.userId = userId;
  49. }
  50. public Integer getCompanyId() {
  51. return companyId;
  52. }
  53. public void setCompanyId(Integer companyId) {
  54. this.companyId = companyId;
  55. }
  56. public Integer getPublishUserId() {
  57. return publishUserId;
  58. }
  59. public void setPublishUserId(Integer publishUserId) {
  60. this.publishUserId = publishUserId;
  61. }
  62. public Integer getPositionId() {
  63. return positionId;
  64. }
  65. public void setPositionId(Integer positionId) {
  66. this.positionId = positionId;
  67. }
  68. public Integer getResumeType() {
  69. return resumeType;
  70. }
  71. public void setResumeType(Integer resumeType) {
  72. this.resumeType = resumeType;
  73. }
  74. public String getStatus() {
  75. return status;
  76. }
  77. public void setStatus(String status) {
  78. this.status = status;
  79. }
  80. public Date getCreateTime() {
  81. return createTime;
  82. }
  83. public void setCreateTime(Date createTime) {
  84. this.createTime = createTime;
  85. }
  86. public Date getUpdateTime() {
  87. return updateTime;
  88. }
  89. public void setUpdateTime(Date updateTime) {
  90. this.updateTime = updateTime;
  91. }
  92. @Override
  93. public String toString() {
  94. return "Order{" +
  95. "id=" + id +
  96. ", del=" + del +
  97. ", userId=" + userId +
  98. ", companyId=" + companyId +
  99. ", publishUserId=" + publishUserId +
  100. ", positionId=" + positionId +
  101. ", resumeType=" + resumeType +
  102. ", status='" + status + '\'' +
  103. ", createTime=" + createTime +
  104. ", updateTime=" + updateTime +
  105. '}';
  106. }
  107. }

repository

  1. package com.galaxy.repository;
  2. import com.galaxy.entity.Order;
  3. import org.springframework.data.jpa.repository.JpaRepository;
  4. /**
  5. * @author lane
  6. * @date 2021年07月27日 下午7:14
  7. */
  8. public interface OrderRepository extends JpaRepository<Order,Long> {
  9. }

application.properties

  1. spring.shardingsphere.datasource.names=master-0,slave-1,slave-2,master-1,slave-3,slave-4
  2. spring.shardingsphere.props.sql.show=true
  3. spring.shardingsphere.datasource.master-0.type=com.zaxxer.hikari.HikariDataSource
  4. spring.shardingsphere.datasource.master-0.driver-class-name=com.mysql.jdbc.Driver
  5. spring.shardingsphere.datasource.master-0.jdbc-url=jdbc:mysql://172.16.94.5:3306/lane3?useUnicode=true&useSSL=false
  6. spring.shardingsphere.datasource.master-0.username=root
  7. spring.shardingsphere.datasource.master-0.password=root
  8. spring.shardingsphere.datasource.slave-1.type=com.zaxxer.hikari.HikariDataSource
  9. spring.shardingsphere.datasource.slave-1.driver-class-name=com.mysql.jdbc.Driver
  10. spring.shardingsphere.datasource.slave-1.jdbc-url=jdbc:mysql://172.16.94.6:3306/lane3?useUnicode=true&useSSL=false
  11. spring.shardingsphere.datasource.slave-1.username=root
  12. spring.shardingsphere.datasource.slave-1.password=root
  13. spring.shardingsphere.datasource.slave-2.type=com.zaxxer.hikari.HikariDataSource
  14. spring.shardingsphere.datasource.slave-2.driver-class-name=com.mysql.jdbc.Driver
  15. spring.shardingsphere.datasource.slave-2.jdbc-url=jdbc:mysql://172.16.94.10:3306/lane3?useUnicode=true&useSSL=false
  16. spring.shardingsphere.datasource.slave-2.username=root
  17. spring.shardingsphere.datasource.slave-2.password=root
  18. spring.shardingsphere.datasource.master-1.type=com.zaxxer.hikari.HikariDataSource
  19. spring.shardingsphere.datasource.master-1.driver-class-name=com.mysql.jdbc.Driver
  20. spring.shardingsphere.datasource.master-1.jdbc-url=jdbc:mysql://172.16.94.17:3306/lane5?useUnicode=true&useSSL=false
  21. spring.shardingsphere.datasource.master-1.username=root
  22. spring.shardingsphere.datasource.master-1.password=root
  23. spring.shardingsphere.datasource.slave-3.type=com.zaxxer.hikari.HikariDataSource
  24. spring.shardingsphere.datasource.slave-3.driver-class-name=com.mysql.jdbc.Driver
  25. spring.shardingsphere.datasource.slave-3.jdbc-url=jdbc:mysql://172.16.94.18:3306/lane5?useUnicode=true&useSSL=false
  26. spring.shardingsphere.datasource.slave-3.username=root
  27. spring.shardingsphere.datasource.slave-3.password=root
  28. spring.shardingsphere.datasource.slave-4.type=com.zaxxer.hikari.HikariDataSource
  29. spring.shardingsphere.datasource.slave-4.driver-class-name=com.mysql.jdbc.Driver
  30. spring.shardingsphere.datasource.slave-4.jdbc-url=jdbc:mysql://172.16.94.19:3306/lane5?useUnicode=true&useSSL=false
  31. spring.shardingsphere.datasource.slave-4.username=root
  32. spring.shardingsphere.datasource.slave-4.password=root
  33. spring.shardingsphere.sharding.tables.c_order.database-strategy.inline.sharding-column=user_id
  34. spring.shardingsphere.sharding.tables.c_order.database-strategy.inline.algorithm-expression=master-$->{user_id % 2}
  35. spring.shardingsphere.sharding.tables.c_order.actual-data-nodes=master-$->{0..1}.c_order
  36. spring.shardingsphere.sharding.tables.c_order.key-generator.column=id
  37. spring.shardingsphere.sharding.tables.c_order.key-generator.type=SNOWFLAKE
  38. spring.shardingsphere.sharding.master-slave-rules.master-0.master-data-source-name=master-0
  39. spring.shardingsphere.sharding.master-slave-rules.master-0.slave-data-source-names=slave-1,slave-2
  40. #spring.shardingsphere.masterslave.load-balance-algorithm-type=ROUND_ROBIN
  41. spring.shardingsphere.sharding.master-slave-rules.master-1.master-data-source-name=master-1
  42. spring.shardingsphere.sharding.master-slave-rules.master-1.slave-data-source-names=slave-3,slave-4

test

  1. /**
  2. * @author lane
  3. * @date 2021年07月27日 下午7:16
  4. */
  5. @RunWith(SpringRunner.class)
  6. @SpringBootTest(classes = ShardingBootRunApplication.class)
  7. public class ShardingTest {
  8. @Autowired
  9. private OrderRepository orderRepository;
  10. @org.junit.Test
  11. public void test(){
  12. for (int idx = 0; idx < 4; ++idx) {
  13. Order order = new Order();
  14. order.setCompanyId(1);
  15. order.setCreateTime(new Date());
  16. order.setDel(false);
  17. order.setPositionId(1);
  18. order.setStatus("WAITING");
  19. order.setPublishUserId(1);
  20. order.setResumeType(1);
  21. order.setUpdateTime(new Date());
  22. order.setUserId(idx);
  23. orderRepository.save(order);
  24. }
  25. }
  26. @Test
  27. public void testSlave(){
  28. List<Order> all = orderRepository.findAll();
  29. System.out.println(all);
  30. }
  31. }

测试分库分表和主从同步结果

通过 Master1 和 Master11 的查询结果可以看出分库成功

通过 Slave1 和 Slave11 可以看到主从同步 OK

master1

  1. mysql> select * from c_order \G;
  2. *************************** 1. row ***************************
  3. id: 626865956605394944
  4. is_del:
  5. user_id: 0
  6. company_id: 1
  7. publish_user_id: 1
  8. position_id: 1
  9. resume_type: 1
  10. status: WAITING
  11. create_time: 2021-07-27 19:41:30
  12. update_time: 2021-07-27 19:41:30
  13. *************************** 2. row ***************************
  14. id: 626865957251317760
  15. is_del:
  16. user_id: 2
  17. company_id: 1
  18. publish_user_id: 1
  19. position_id: 1
  20. resume_type: 1
  21. status: WAITING
  22. create_time: 2021-07-27 19:41:31
  23. update_time: 2021-07-27 19:41:31
  24. 2 rows in set (0.00 sec)

slave1

  1. mysql> use lane3
  2. mysql> select * from c_order \G
  3. *************************** 1. row ***************************
  4. id: 626865956605394944
  5. is_del:
  6. user_id: 0
  7. company_id: 1
  8. publish_user_id: 1
  9. position_id: 1
  10. resume_type: 1
  11. status: WAITING
  12. create_time: 2021-07-27 19:41:30
  13. update_time: 2021-07-27 19:41:30
  14. *************************** 2. row ***************************
  15. id: 626865957251317760
  16. is_del:
  17. user_id: 2
  18. company_id: 1
  19. publish_user_id: 1
  20. position_id: 1
  21. resume_type: 1
  22. status: WAITING
  23. create_time: 2021-07-27 19:41:31
  24. update_time: 2021-07-27 19:41:31
  25. 2 rows in set (0.00 sec)

master11

  1. mysql> select * from c_order \G;
  2. *************************** 1. row ***************************
  3. id: 626865957129682945
  4. is_del:
  5. user_id: 1
  6. company_id: 1
  7. publish_user_id: 1
  8. position_id: 1
  9. resume_type: 1
  10. status: WAITING
  11. create_time: 2021-07-27 19:41:31
  12. update_time: 2021-07-27 19:41:31
  13. *************************** 2. row ***************************
  14. id: 626865957284872193
  15. is_del:
  16. user_id: 3
  17. company_id: 1
  18. publish_user_id: 1
  19. position_id: 1
  20. resume_type: 1
  21. status: WAITING
  22. create_time: 2021-07-27 19:41:31
  23. update_time: 2021-07-27 19:41:31
  24. 2 rows in set (0.00 sec)

slave11

  1. mysql> use lane5;
  2. mysql> select * from c_order\G;
  3. *************************** 1. row ***************************
  4. id: 626865957129682945
  5. is_del:
  6. user_id: 1
  7. company_id: 1
  8. publish_user_id: 1
  9. position_id: 1
  10. resume_type: 1
  11. status: WAITING
  12. create_time: 2021-07-27 19:41:31
  13. update_time: 2021-07-27 19:41:31
  14. *************************** 2. row ***************************
  15. id: 626865957284872193
  16. is_del:
  17. user_id: 3
  18. company_id: 1
  19. publish_user_id: 1
  20. position_id: 1
  21. resume_type: 1
  22. status: WAITING
  23. create_time: 2021-07-27 19:41:31
  24. update_time: 2021-07-27 19:41:31
  25. 2 rows in set (0.00 sec)

测试读写分离结果

分别修改下 slave1 和 slave11 中 c_order 表的数据

  1. #slave1
  2. update c_order set status ='slave1';
  3. #slave11
  4. update c_order set status ='slave11';

查看读取的数据,可以看到读取到的是从库中 c_order 的数据,成功实现读写分离

  1. [Order{id=626865956605394944, del=false, userId=0, companyId=1, publishUserId=1, positionId=1, resumeType=1, status='slave1',
  2. createTime=2021-07-27 19:41:30.0, updateTime=2021-07-27 19:41:30.0},
  3. Order{id=626865957251317760, del=false, userId=2, companyId=1, publishUserId=1, positionId=1, resumeType=1, status='slave1',
  4. createTime=2021-07-27 19:41:31.0, updateTime=2021-07-27 19:41:31.0},
  5. Order{id=626865957129682945, del=false, userId=1, companyId=1, publishUserId=1, positionId=1, resumeType=1, status='slave11',
  6. createTime=2021-07-27 19:41:31.0, updateTime=2021-07-27 19:41:31.0},
  7. Order{id=626865957284872193, del=false, userId=3, companyId=1, publishUserId=1, positionId=1, resumeType=1, status='slave11',
  8. createTime=2021-07-27 19:41:31.0, updateTime=2021-07-27 19:41:31.0}]
  9. 2