Docker爱看不看系列: mysql主从复制

在实际开发中,对数据库的操作无非就是读和写,而且在互联网产品中,读多于写,所以为了缓解主数据库的压力,我们把读和写的操作给分离了,这样可以让读数据的操作更加顺畅,避免了产生表锁等。读写分离是基于主从同步来实现了,从数据库复制了主数据库的数据,当住数据库宕机的时候,也可以切换其中的某一台从数据库为主数据库,冗余的数据保证了系统的高可用性。

下面我就演示下读写分离是如何搭建的。

为了节约成本(太穷),我选在docker下创建mysql服务,没有docker的同学们,可以参考菜鸟教程,这个还是挺详细的,而且还有mysql容器的搭建,菜鸟教程链接

如果不想用docker的同学们也可以选择虚拟机,云服务器,本机等等,只要有两个或两个以上的mysql服务,都不影响以下的操作。

接下来我先创建三个mysql服务(一个Master,两个Slave),如果你是root权限就不用加sudo了。

# 创建mysql-master服务
sudo docker run -itd --name mysql-master -p 3308:3306 -e MYSQL_ROOT_PASSWORD=root mysql:5.7
# 创建mysql-slave1服务
sudo docker run -itd --name mysql-slave1 -p 3309:3306 -e MYSQL_ROOT_PASSWORD=root mysql:5.7
# 创建mysql-slave2服务
sudo docker run -itd --name mysql-slave2 -p 3310:3306 -e MYSQL_ROOT_PASSWORD=root mysql:5.7

接下来,我们通过 sudo docker ps 查看当前运行的容器

CONTAINER ID        IMAGE                   COMMAND                  CREATED             STATUS              PORTS                                                                                        NAMES
203507cbea48        mysql:5.7               "docker-entrypoint.s…"   8 seconds ago       Up 6 seconds        33060/tcp, 0.0.0.0:3310->3306/tcp                                                            mysql-slave2
f6bc2477dd22        mysql:5.7               "docker-entrypoint.s…"   25 seconds ago      Up 22 seconds       33060/tcp, 0.0.0.0:3309->3306/tcp                                                            mysql-slave1
32c7a30f98d7        mysql:5.7               "docker-entrypoint.s…"   44 seconds ago      Up 42 seconds       33060/tcp, 0.0.0.0:3308->3306/tcp                                                            mysql-master

接下来我们用Navicat来访问,IP为你宿主机的IP,测试之前请保证你可以ping通你的虚拟机,测试结果如下:

接下来我们回到命令行窗口,进入mysql-slave的伪终端,这里的mysql-master可以换成容器的ID

sudo docker exec -it mysql-master /bin/bash

进入之后,我们需要修改mysqld.cnf文件

# 指令
vi /etc/mysql/mysql.conf.d/mysqld.cnf 
# 结果
bash: vi: command not found

这里没有vi指令,所以我们就安装vim编辑器,下面我也是通过指令和结果的方式来展示(docker下需要这步操作)

# 指令 安装vim
apt-get install vim
# 结果 无法安装
Reading package lists... Done
Building dependency tree       
Reading state information... Done
E: Unable to locate package vim

# 指令 更新apt-get
apt-get update
# 结果 更新成功
Get:1 http://security.debian.org/debian-security buster/updates InRelease [65.4 kB]
Get:2 http://deb.debian.org/debian buster InRelease [121 kB]                                                                  
Get:3 http://repo.mysql.com/apt/debian buster InRelease [21.5 kB]
Get:4 http://security.debian.org/debian-security buster/updates/main amd64 Packages [204 kB]
Get:5 http://deb.debian.org/debian buster-updates InRelease [51.9 kB]           
Get:6 http://repo.mysql.com/apt/debian buster/mysql-5.7 amd64 Packages [5685 B]
Get:7 http://deb.debian.org/debian buster/main amd64 Packages [7905 kB]
Get:8 http://deb.debian.org/debian buster-updates/main amd64 Packages [7868 B]                                                                                  
Fetched 8383 kB in 26s (328 kB/s)                                                                                                                               
Reading package lists... Done

# 指令 安装vim
apt-get install vim
# 结果太长就不复制了

接下来我们继续编辑mysql.cnf文件

[mysqld]
## 同一局域网内注意要唯一
server-id=1000  
## 开启二进制日志功能,可以随便取(关键)
log-bin=mysql-bin


按Esc 输入:wq 保存退出 

下面我们重启mysql服务 service mysql restart

使用上面的指令后我们需要重启mysql-master容器

# 由于之前通过run指令创建了容器,这里我们可以通过start命令启动容器
# 具体可以通过 sudo docker --help 查看指令
sudo docker restart mysql-master

我们再次进入伪终端,并进入mysql

sudo docker exec -it mysql-master /bin/bash
mysql -u root -p

创建一个slave的用户,并赋予权限

CREATE USER 'slave'@'%' IDENTIFIED BY 'slave';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%';

master的配置到此就结束了,接下来我们开始配置slave,我们也需要修改mysqld.cnf,

# mysql-slave1
[mysqld]
## 设置server_id,注意要唯一
server-id=1001 
## 开启二进制日志功能,以备Slave作为其它Slave的Master时使用
log-bin=mysql-slave1-bin   
## relay_log配置中继日志
relay_log=edu1-mysql-relay-bin  

---

# mysql-slave2
[mysqld]
## 设置server_id,注意要唯一
server-id=1002 
## 开启二进制日志功能,以备Slave作为其它Slave的Master时使用
log-bin=mysql-slave2-bin   
## relay_log配置中继日志
relay_log=edu2-mysql-relay-bin  

跟master操作一样,我们也需要重启mysql服务和docker容器,

重复动作这里不再演示

接下来进入mysql-master,执行 show master status;

mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 |      617 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

接下来我们查看容器的独立IP 

maochd@ubuntu:~$ sudo docker inspect --format='{{.NetworkSettings.IPAddress}}' mysql-master
172.17.0.5
maochd@ubuntu:~$ sudo docker inspect --format='{{.NetworkSettings.IPAddress}}' mysql-slave1
172.17.0.6
maochd@ubuntu:~$ sudo docker inspect --format='{{.NetworkSettings.IPAddress}}' mysql-slave2
172.17.0.7

然后我们进去mysql-slave1,执行

change master to master_host='172.17.0.5', master_user='slave', master_password='slave', master_port=3306, master_log_file='mysql-bin.000001', master_log_pos= 617, master_connect_retry=30;

master_host  

mysql-master的地址
master_portmysql-master的端口号,指的是容器的端口号
master_user用于数据同步的用户
master_password用于同步的用户的密码
master_log_file指定 Slave 从哪个日志文件开始复制数据,即上文中提到的 File 字段的值
master_log_pos从哪个 Position 开始读,即上文中提到的 Position 字段的值
master_connect_retry如果连接失败,重试的时间间隔,单位是秒,默认是60秒

我们执行 show slave status \G;

mysql> show slave status \G;
*************************** 1. row ***************************
               Slave_IO_State: 
                  Master_Host: 172.17.0.5
                  Master_User: slave
                  Master_Port: 3306
                Connect_Retry: 30
              Master_Log_File: mysql-bin.000001
          Read_Master_Log_Pos: 617
               Relay_Log_File: edu1-mysql-relay-bin.000001
                Relay_Log_Pos: 4
        Relay_Master_Log_File: mysql-bin.000001
             Slave_IO_Running: No
            Slave_SQL_Running: No
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 0
                   Last_Error: 
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 617
              Relay_Log_Space: 154
              Until_Condition: None
               Until_Log_File: 
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File: 
           Master_SSL_CA_Path: 
              Master_SSL_Cert: 
            Master_SSL_Cipher: 
               Master_SSL_Key: 
        Seconds_Behind_Master: NULL
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error: 
               Last_SQL_Errno: 0
               Last_SQL_Error: 
  Replicate_Ignore_Server_Ids: 
             Master_Server_Id: 0
                  Master_UUID: 
             Master_Info_File: /var/lib/mysql/master.info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: 
           Master_Retry_Count: 86400
                  Master_Bind: 
      Last_IO_Error_Timestamp: 
     Last_SQL_Error_Timestamp: 
               Master_SSL_Crl: 
           Master_SSL_Crlpath: 
           Retrieved_Gtid_Set: 
            Executed_Gtid_Set: 
                Auto_Position: 0
         Replicate_Rewrite_DB: 
                 Channel_Name: 
           Master_TLS_Version: 
1 row in set (0.00 sec)

 正常情况下,SlaveIORunning 和 SlaveSQLRunning 都是No,因为我们还没有开启主从复制过程。使用start slave开启主从复制过程,然后再次查询主从同步状态show slave status \G;。

 Slave_IO_Running: Yes
 Slave_SQL_Running: Yes

SlaveIORunning 和 SlaveSQLRunning 都是Yes,说明主从复制已经开启。

接下来对mysql-slave2做同样的操作。

接下来我们在mysql-master中创建一个数据库,发现mysql-slave1和mysql-slave2中也都创建了,说明主从同步已经完成了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值