本文共 6981 字,大约阅读时间需要 23 分钟。
为了确保数据库产品的稳定性,很多数据库拥有双机热备功能,也就是,第一台数据库服务器对外提供增删改业务的生产服务器,第二台数据库服务器,主要进行读的操作。
原理:让主数据库(master)处理事务性增删改操作,而从数据库(slave)处理select 查询操作。
[mysqld]basedir=/usr/local/mysqldatadir=/usr/local/mysql/datasocket=/tmp/mysql.sockuser=mysqlport=3306# Master# 开启日志log-bin = mysql-bin# 日志格式按行同步binlog-format = ROW# 设置服务id,主从不能一致server-id = 1# 设置需要同步的数据库binlog-do-db = user_db# 设置忽略系统库同步binlog-ignore-db = mysqlbinlog-ignore-db = information_schemabinlog-ignore-db = performance_schemabinlog-ignore-db = sys# Disabling symbolic-links is recommended to prevent assorted security riskssymbolic-links=0# character configcharacter_set_server=utf8mb4[mysqld_safe]log-error=/usr/local/mysql/data/mysql.logpid-file=/usr/local/mysql/data/mysql.pid# include all files from the config directory!includedir /etc/my.cnf.d
主要配置
# Master# 开启日志log-bin = mysql-bin# 日志格式按行同步binlog-format = ROW# 设置服务id,主从不能一致server-id = 1# 设置需要同步的数据库binlog-do-db = user_db# 设置忽略系统库同步binlog-ignore-db = mysqlbinlog-ignore-db = information_schemabinlog-ignore-db = performance_schemabinlog-ignore-db = sys
[mysqld]basedir=/usr/local/mysqldatadir=/usr/local/mysql/datasocket=/tmp/mysql.sockuser=mysqlport=3306# Slave# 开启日志log-bin = mysql-bin# 日志按照行进行数据同步binlog-format = ROW# 设置服务id,主从不能一致server-id = 2# 设置需要同步的数据库replicate-do-db=user_db# 设置忽略系统库replicate-ignore-db = mysql replicate-ignore-db = information_schema replicate-ignore-db = performance_schema replicate-ignore-db = sys#replicate-wild-ignore_table = mysql.%#replicate-wild-ignore_table = information_schema.%#replicate-wildignore_table = performance_schema.%#replicate-wild-ignore_table = sys.%# Disabling symbolic-links is recommended to prevent assorted security riskssymbolic-links=0#character configcharacter_set_server=utf8mb4[mysqld_safe]log-error=/usr/local/mysql/data/mysql.logpid-file=/usr/local/mysql/data/mysql.pid## include all files from the config directory#!includedir /etc/my.cnf.d
主要配置
# Slave# 开启日志log-bin = mysql-bin# 日志按照行进行数据同步binlog-format = ROW# 设置服务id,主从不能一致server-id = 2# 设置需要同步的数据库replicate-do-db=user_db# 设置忽略系统库replicate-ignore-db = mysql replicate-ignore-db = information_schema replicate-ignore-db = performance_schema replicate-ignore-db = sys
mysql -uroot -p123456 -h192.168.124.12
CREATE USER 'sync'@'%' IDENTIFIED WITH mysql_native_password BY '123456';# 授权主备复制专用账号GRANT REPLICATION SLAVE ON *.* TO 'sync'@'%';show grants for sync;# 刷新权限flush privileges;# 确认位点,记录下文件名及位点show master status;
mysql 数据库中查询user表获取文件名和点位
mysql-bin.0000011 156
mysql -uroot -p123456 -h192.168.124.11 -P3306
# 先停止同步stop slave;# 修改从库指向到主库,使用上一步记录的文件名以及位点CHANGE MASTER TO master_host='192.168.124.12',master_port=3306,master_user='sync',master_password='123456',master_log_file='mysql-bin.000011',master_log_pos=156;# 启动同步start slave;# 查看slave 的状态show slave status;
CREATE SCHEMA `testdb` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ;
CREATE TABLE `testdb`.`t_user` ( `id` BIGINT NOT NULL, `name` VARCHAR(45) NOT NULL, `age` INT NOT NULL, PRIMARY KEY (`id`))ENGINE = InnoDBDEFAULT CHARACTER SET = utf8mb4COLLATE = utf8mb4_unicode_ci;
INSERT INTO `testdb`.`t_user` (`id`, `name`, `age`) VALUES ('1', 'zhangsan', '3');
需要注意的是数据库的字符集编码必须一致
# sharding-JDBC分片策略(主从复制配置)# 配置数据源,给数据源命名spring.shardingsphere.datasource.names=m0,s0# 配置数据源具体内容,连接池、驱动、地址、用户名和密码# testdb 主服务器spring.shardingsphere.datasource.m0.type=com.alibaba.druid.pool.DruidDataSourcespring.shardingsphere.datasource.m0.driver-class-name=com.mysql.cj.jdbc.Driverspring.shardingsphere.datasource.m0.url=jdbc:mysql://192.168.124.12:3306/testdb?serverTimezone=GMT%2B8spring.shardingsphere.datasource.m0.username=rootspring.shardingsphere.datasource.m0.password=123456# 配置数据源具体内容,连接池、驱动、地址、用户名和密码# testdb 从服务器spring.shardingsphere.datasource.s0.type=com.alibaba.druid.pool.DruidDataSourcespring.shardingsphere.datasource.s0.driver-class-name=com.mysql.cj.jdbc.Driverspring.shardingsphere.datasource.s0.url=jdbc:mysql://192.168.124.11:3306/testdb?serverTimezone=GMT%2B8spring.shardingsphere.datasource.s0.username=rootspring.shardingsphere.datasource.s0.password=123456# 一个实体类对应两张表,覆盖spring.main.allow-bean-definition-overriding=true# 主从库逻辑数据源定义 ds0 为testdbspring.shardingsphere.sharding.master-slave-rules.ds0.master-data-source-name=m0spring.shardingsphere.sharding.master-slave-rules.ds0.slave-data-source-names=s0# t_user 分表策略,固定分配至ds0的t_user真实表spring.shardingsphere.sharding.tables.t_user.actual-data-nodes=ds$->{0}.t_userspring.shardingsphere.sharding.tables.t_user.key-generator.column=idspring.shardingsphere.sharding.tables.t_user.key-generator.type=SNOWFLAKE# 打印sql输出日志spring.shardingsphere.props.sql.show=true
package com.ccb.sharding.po;import com.baomidou.mybatisplus.annotation.TableId;import com.baomidou.mybatisplus.annotation.TableName;@TableName("t_user")public class Student { @TableId("id") private Long id; private String name; private int age; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Student{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + '}'; }}
package com.ccb.sharding.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;import com.ccb.sharding.po.Student;import com.ccb.sharding.po.User;import org.springframework.stereotype.Repository;@Repositorypublic interface StudentMapper extends BaseMapper{ }
package com.ccb.sharding;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;import com.ccb.sharding.mapper.StudentMapper;import com.ccb.sharding.po.Student;import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;@SpringBootTestclass ShardingApplicationTests { @Autowired StudentMapper studentMapper; // ================= 测试读写分离 ====================== @Test public void addStudentMaster() { Student student = new Student(); student.setName("Lily"); student.setAge(23); studentMapper.insert(student); } @Test public void getStudentSlave(){ QueryWrapper queryWrapper = new QueryWrapper(); queryWrapper.eq("id",1278468912563892226L); Student student = studentMapper.selectOne(queryWrapper); System.out.println(student); }}
Result
以上可以看到主从都有数据,并且写入时是主库master,读取时是从库slave,实现了目标主从复制、读写分离
转载地址:http://vtym.baihongyu.com/