MySql主从以及用Docker部署

发布于 2020-01-02  328 次阅读


介绍

MySql主从一般1主多从,当然MySql5.7开始多主一从,还有双主复制、级联复制,这里暂时不说,现在之说1主多从,利用的是MySql的replication来保证数据一致,但是必然会有延迟、不一致性,使用PCX集群可以保证一致.

其实就是把主库的binlog文件传给从库的relaylog,然后sql读取同步。

从节点I/O线程

当从节点上执行`start slave`命令之后,从节点会创建一个I/O线程用来连接主节点,请求主库中更新的bin-log。I/O线程接收到主节点binlog dump 进程发来的更新之后,保存在本地relay-log中。

从节点SQL线程

SQL线程负责读取relay log中的内容,解析成具体的操作并执行,最终保证主从数据的一致性。

开始搭建

mysql的配置

在多台服务器上安装好MySql后,修改my.cnf,不知道位置可以whereis my.cnf 或者 whereis mysql查看,修改完记得service mysql restart或者systemctl mysql restart重启服务,还有show global variables;可以查看mysql的所有配置信息。

首先修改主库的my.cnf,加入以下两行

log-bin=mysql-bin    //[必须]启用二进制日志
server-id=1          //[必须]服务器标识ID,每台服务器唯一

然后是从库的my.cnf,注意:service-id每台服务器都不可一样,一般主库为1,从库往后排

log-bin=mysql-bin    //[必须]启用二进制日志
server-id=2          //[必须]服务器标识ID,每台服务器唯一 

还有以下配置,看各人需要,配置同步哪些表

# 不同步哪些数据库  
binlog-ignore-db = mysql  
binlog-ignore-db = test  
binlog-ignore-db = information_schema  
  
# 只同步哪些数据库,除此之外,其他不同步  
binlog-do-db = order

然后进入主库的mysql,mysql -uroot -p 进入后执行命令,修改可以被任何客户端连接,mysql_native_password是身份验证插件,记得一定要用这个,MySql8.0开始默认为caching_sha2_password ,从库会连不上提示错误的,在mysql库的user表里可以看到用户所使用的身份验证插件。

mysql>ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '密码';
mysql>flush privileges;   #刷新权限

注意:上面我是直接用的root用户作为从库连接凭证,最好还是新建个从库专门用的账户,如下

mysql>CREATE USER '用户名'@'%' IDENTIFIED BY '密码';   #创建用户
mysql>GRANT REPLICATION SLAVE ON *.* TO '用户名'@'%';    #分配REPLICATION(主从复制)权限
mysql>flush privileges;   #刷新权限

账户创建完之后,然后在主库中再执行 show master status; 查看数据库状态 ,记住这个FilePosition,后面从库要用到

然后进入从库的MySql,执行以下命令,修改x.x.x.x为主库IP,user,password为主库用户名和密码,log_file和log_pos就是上图的这个File和Position

mysql>change master to
master_host='x.x.x.x',
master_user='root',
master_log_file='mysql-bin.000004',
master_log_pos=1602,
master_port=3306,
master_password='123456';

执行完之后,执行 start slave; 启动从服务器复制功能,如果配置错了,执行 stop slave; 再如上配置下,再 start slave; 即可

执行完之后,在从库中执行 show slave status\G; 可以查看主从连接状态,只要Slave IO RunningSlave SQL Running都为Yes就正常,还有前面的Slave_IO_State,对应的信息显示的是Waiting for master to send event...

这个时候就已经完成了,可以去连接主库的mysql去创建表和字段,这个时候再去从库看就可以发现,已经同步过来了(可能有一点延时)

Docker下安装MySQL

简单粗暴,直接上docker-compose.yml配置,如下,主要注意的是volumes配置,这个是使用主机的目录来存放数据和日志,还有使用主机的my.cnf配置文件,格式如下

volumes:
   - 主机路径:容器路径

应该注意到我下面yml配置中用的是./ ,意思是docker-compose.yml所在的当前位置下的文件夹和文件,如图

这些用到的目录和配置文件要提前新建好,然后将一下代码保存为docker-compose.yml,放在如上图位置

version: '3' 
services:
  mysqlMaster: #容器名称
    image: mysql:latest #镜像名称
    networks: #所用网络
      - backend
    environment: #环境变量
      - TZ=Asia/Shanghai #时区
      - MYSQL_ROOT_PASSWORD=123456
    volumes: #目录/文件映射  主机路径:容器路径
      - ./data/master:/var/lib/mysql
      - ./log/master:/var/log/mysql
      - ./config/master.cnf:/etc/my.cnf
    deploy:
      replicas: 1 #工作节点上运行的任务数
      restart_policy: #重启策略
        condition: any
      resources:
        limits: #资源限制
          cpus: "0.2"
          memory: 512M
    ports: #外网:容器 端口映射
      - 33060:3306
  mysqlSlave1:
    image: mysql:latest 
    networks:
      - backend
    environment: 
      - TZ=Asia/Shanghai #时区
      - MYSQL_ROOT_PASSWORD=123456
    volumes: 
      - ./data/slave1:/var/lib/mysql
      - ./log/slave1:/var/log/mysql
      - ./config/slave1.cnf:/etc/my.cnf
    deploy:
      replicas: 1      
      restart_policy: 
        condition: any
      resources:
        limits: 
          cpus: "0.2"
          memory: 384M
    ports: 
      - 33061:3306
  mysqlSlave2:
    image: mysql:latest 
    networks:
      - backend
    environment: 
      - TZ=Asia/Shanghai #时区
      - MYSQL_ROOT_PASSWORD=123456
    volumes: 
      - ./data/slave2:/var/lib/mysql
      - ./log/slave2:/var/log/mysql
      - ./config/slave2.cnf:/etc/my.cnf
    deploy:
      replicas: 1        
      restart_policy: 
        condition: any
      resources:
        limits: 
          cpus: "0.2"
          memory: 384M
    ports: 
      - 33062:3306
networks:
  backend:

然后在docker-compose.yml所在目录执行以下命令,创建并运行容器

docker-compose up -d

下面我放一下master的my.cnf配置,slave的my.cnf也只是改下server-id参数就行

[mysqld]
log-bin=mysql-bin
server-id=1
character-set-server=utf8
datadir=/var/lib/mysql
innodb_buffer_pool_size = 256M
innodb_use_native_aio = 0
key_buffer_size = 128M
max_allowed_packet = 486M
myisam_sort_buffer_size = 128M
net_buffer_length = 2K
read_buffer_size = 256K
read_rnd_buffer_size = 256K
skip-external-locking
skip-name-resolve
socket=/var/lib/mysql/mysql.sock
sort_buffer_size = 64K
table_open_cache = 256
thread_stack = 240K
user=mysql

[mysqld_safe]
log-error=/var/log/mysql/mysqld.log
pid-file=/var/lib/mysql/mysqld.pid

docker run命令版

docker run -p 33066:3306 --name mysql-master --net=mysql_backend \
-e MYSQL_ROOT_PASSWORD=123456 \
-v /home/docker/mysql/data/master:/var/lib/mysql \
-v /home/docker/mysql/config/master.cnf:/etc/my.cnf -d mysql:latest

...省略

踩坑跳坑

1.容器是跑起来了,但是发现mysql没使用主机的my.cnf文件,而是使用的自己默认的my.cnf,于是查看日志发现有个warning: can't allow writable /config/slave2.cnf 什么的,意思就是容器如果使用主机的这个mysql配置文件,不能为可写,于是权限修改为444,都只能读,然后重启容器,mysql配置生效。

2.从库执行过change master...和start slave;命令后,执行show slave status;发现有问题,Slave_IO_State显示:Authentication plugin 'caching_sha2_password' reported error: Authentication requires secure connection,关键字就是这个
caching_sha2_password ,mysql8.0默认的就是这个,网上搜寻一下,也就是说把它换成mysql_native_password,代码如下

ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '密码';
FLUSH PRIVILEGES;

3.还有一个网上看到的,防火墙问题,Slave_IO_Running: Connecting  # 出现错误,IO线程处于正在连接状态,关掉主从的防火墙即可

4.注意检查账号权限,在主库新建过账号,记得主库中mysql -uroot -p 连接执行select什么的检查下,本文使用的直接是root偷懒了,安全起见使用特定用户授予REPLICATION 权限,用于从库的连接。