5. 安装 win 版 MySQL

主从复制

  • 负载均衡
  • 失败迁移

    windows

  • 已安装 MySQL 的完全卸载

    • 卸载
    • 删除缓存目录 C:\ProgramData\MySQL
    • 删除注册表 regedit 中所有 mysql 相关配置

      MySQL 授权远程访问

      ```java / 在被访问的虚拟机 MySQL 中输入如下语句 / GRANT ALL PRIVILEGES ON . TO ‘root’@’%’ IDENTIFIED BY ‘root’ WITH GRANT OPTION; FLUSH PRIVILEGES;

/ 如果仍然没有成功,在 linux 执行关闭防火墙 / service iptables stop; / centos 7 以后使用 / systemctl stop firewalld;

  1. <a name="x2LSa"></a>
  2. # 6. 主从同步原理
  3. - 核心:二进制日志
  4. <a name="RO4yo"></a>
  5. ## 同步过程
  6. - (1) master
  7. - database-->binary log
  8. - master 将改变的数据记录在本地的二进制日志中
  9. - 该过程称之为二进制日志事件
  10. - (2) slave
  11. - (2.1) binary log(master)-->IO 线程
  12. - slave IO 线程获取 master 在 binary log 中的日志
  13. - (2.2) IO 线程-->relay-log
  14. - slave 将获取到的日志拷贝到 relay log(中继日志文件)中
  15. - (2.3) relay-log-->SQL 线程-->database
  16. - 中继日志事件
  17. - MySQL 实现主从复制是异步,串行的,有延迟
  18. <a name="njRhO"></a>
  19. # 7. 主从同步实战
  20. - windows(mysql: my.ini)
  21. - linux(mysql: my.cnf)
  22. <a name="oRnLF"></a>
  23. ## 配置前准备
  24. - 关闭防火墙
  25. - linux
  26. - systemctl stop firewalld;
  27. - windows 在设置里关闭
  28. - 授权允许远程访问
  29. - GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'root' WITH GRANT OPTION;
  30. - FLUSH PRIVILEGES;
  31. <a name="Y69s3"></a>
  32. ## windows 下作为主机的 MySQL 配置 my.ini
  33. ```java
  34. [mysqld]
  35. # id
  36. server-id=1
  37. # 二进制日志文件
  38. log-bin="D:/xxx/data/mysql-bin"
  39. # 错误记录文件
  40. log-error="D:/xxx/data/mysql-error"
  41. # 主从同步时,忽略的数据库
  42. binlog-ignore-db=mysql
  43. # (可选) 指定主从同步时,同步哪些数据库
  44. binlog-do-db=test

windows 中的 mysql 授权从数据库

/* 授权从数据库 */
GRANT REPLICATION slave, reload, super ON *.* TO 'root'@'192.168.2.%' IDENTIFIED BY 'root';
FLUSH PRIVILEGES;

/* 查看数据库状态;每次主从同步前,观察主机状态的最新值 */
show master status;

Linux 下作为从机的 MySQL 配置 my.cnf

vi /etc/my.cnf

[mysqld]
# id
server-id=2

# 二进制日志文件
log-bin=mysql-bin

# (可选) 指定主从同步时,同步哪些数据库
replicate-do-db=test

Linux 中作为从机的 MySQL 授权主机

/* 在 windows 中作为主机的 mysql 中操作 */
/* 获取 master_log_file 和 master_log_pos */
show master status;

/* 在 Linux 中作为从机的 mysql 中操作 */
CHANGE MASTER TO
MASTER_HOST='192.168.2.2',
MASTER_USER='root',
MASTER_PASSWORD='root',
MASTER_PORT=3306,
master_log_file='mysql-bin.000002',
master_log_pos=xxx;

/* 如果报如下错误,进行 STOP SLAVE 操作 */
/* This operation cannot be performed with a running slave; run STOP SLAVE first */
STOP SLAVE;

开启主从同步

start slave;
show slave status \G;

/* 观察 Slave_IO_Running 和 Slave_SQL_Running 确保二者都是 yes */
/* 如果 Slave_IO_Running 不是 yes,可能是主从机中 MySQL 版本不一致导致的,则手动设置 server_id*/
show variables like '%server_id%';
stop slave;
set global server_id=2;
start slave;

测试主从同步

/* 在 windows MySQL 主机中操作 */
use test;
create table tb(id int(4) primary key, name varchar(20) not null);
insert into tb values(1, 'zs');
insert into tb values(2, 'ls');

/* 在 Linux 从机中查看 */
use test;
select * from tb;

1. 主从 Mycat 读写分离,分库分表,haproxy 和 keepalive 架构

MySQL 处理海量数据

  • 主从同步
    • 带来数据冗余
    • 从节点作为备份节点
    • 主从同步,可以实现读写分离(mycat)
  • MySQL 中解决并发问题
    • 读写分离
    • 一般项目中,读操作远大于写操作
    • 减少并发

实现读写分离

  • mycat
    • 读写分离
    • 分库分表
  • haproxy
    • 搭建多个 mycat 集群
    • 防止单点故障
  • 去中心化

    • 多个 haproxy 节点之间发送心跳感知对方是否存活
    • 维护一个虚拟 ip

      2. 架构环境准备

      搭建集群

  • 1 个 windows 主机

  • 5 个 centos7 从机
  • 新增虚拟机配置

    • 内存
    • IP
      • vi /etc/sysconfig/network-scripts/ifcfg-ens33
      • 删除唯一标识符
    • hostname
      • hostnamectl set-hostname bigdata0x
    • 修改映射
      • vi /etc/hosts
      • 主机 + 从机 6 台全部映射
    • ssh
      • 生成密钥
        • ssh-keygen -t rsa
      • 私钥发给自己
        • ssh-copy-id localhost
      • 公钥发给其他节点
        • ssh-copy-id [其他节点的 ip 或者已经配置了映射的 hostname]
      • 检查是否配置成功
        • ssh [其他节点的 hostname]

          3~4. 跨平台 mysql 主从同步,实战 MySQL 主从同步

          关闭防火墙

  • centos7

    • systemctl stop firewalld
  • windows

    • 也可以开放特定端口

      授权 MySQL 权限,各个节点都操作

  • grant all privileges on . to ‘root’@’192.168.2.%’ identified by ‘root’ with grant option;

  • flush privileges;

    配置 mysql

    windows 下主机 MySQL 的 my.ini

[mysqld]
server-id=1
# 二进制日志文件
log-bin="D:/xxx/data/mysql-bin"
# 错误记录文件
log-error="D:/xxx/data/mysql-error"

# mysql 根路径
basedir="D:/xxx/"
# 指定排除的数据库
binlog-ignore-db=mysql


/* 创建数据库 */
create database mydb01;
create database mydb02;

Linux 下从机的 my.cnf

[mysqld]
server-id=2
log-bin=mysql-bin

replicate-do-db=mydb01
replicate-do-db=mydb02
  • 配置后重启 mysql 生效

    设置主从关系

    ```java / 在主机 mysql 中查看/ show master status;

/ 在 slave 中指定 master / change master to master_host=’192.168.2.2’, master_user=’root’, master_password=’root’, master_port=3306, master_log_file=’mysql-bin.00000x’ master_log_pos=107;

<a name="UYvNU"></a>
## 验证主从同步
```java
/* 在 Linux 的从 MySQL 中创建数据库 */
create database mydb01;
create database mydb02;

/* 开启 slave */
start slave;

/* 查看 slave 状态 */
/* 需要保证 Slave_IO_Running, Slave_SQL_Running 两个状态为 yes*/
show slave status;

/* 在主机中创建表并插入数据 */
use mydb01;
create table student01(id int(4), name varchar(10));
insert into student01 values(1, 'zs');

use mydb02;
create table student02(id int(4), name varchar(10));
insert into student02 values(1, 'zs');

/* 在从 slave 查看是否有相应的表和数据 */
use mydb01;
select * from student01;

常见错误解决

slave stop;
reset slave;
change master to ...

5~6. MyCat 安装配置及原理,使用 MyCat 实现主从同步与读写分离

  • 分库分表
    • 水平拆分
      • 同个业务逻辑拆分为多个子库
    • 垂直拆分
      • 按业务逻辑拆分为多个子数据库
  • 读写分离
    • 读—>独立的服务器节点
    • 写—>服务器节点
  • 结构
    • 在 mycat 搭建两个逻辑数据库
    • 写数据在主 mysql 中进行
    • 读数据在从 mysql 中进行

mycat 安装

<a name="zvLbW"></a>
### schmea.xml
```java
    <schema name="mydb" checkSQLschema="false" sqlMaxLimit="100" randomDataNode="dn1">
        <!-- table 标签配置分表 -->
        <!-- rule 属性表示拆分规则 -->
        <table name="student" dataNode="dn1, dn2" rule="mod-long" />
    <!-- 拆分后数据切片的位置 -->
    <!-- dataHost 设置读写分离的主机地址 -->
    <dataNode name="dn1" dataHost="localhost1" database="mydb01" />
    <dataNode name="dn2" dataHost="localhost1" database="mydb02" />
    <!-- 读写分离的主机地址 -->
    <dataHost name="localhost1" maxCon="1000" minCon="10" balance="3"
              writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
        <heartbeat>select user()</heartbeat>
        <!-- can have multi write hosts -->
        <writeHost host="hostM1" url="192.168.2.2:3306" user="root" password="root">
            <readHost host="hostS2" url="192.168.2.128:3306" user="root" password="root" />
        </writeHost>
    </dataHost>
  • dataHost

    • balance 读请求的负载均衡
      • 0 不开启读写分离,所有的读操作,都发送到 writeHost 中
      • 1 全部的 readlyHost 和 stand by writeHost 都参与读操作的负载均衡
      • 2 读请求随机发送给 readHost 和 writeHost
      • 3 读请求随机发送给 writeHost 中的 readHost
        • writeHost 不参与读请求
        • 推荐
    • writeType 写请求的负载均衡
      • 0 写请求先发送给 schema.xml 中的第一个 writeHost
        • 第一个 writeHost 宕机,再自动切换到下一个
        • 切换记录会记录在 conf/dnindex.properties
      • 1 写请求随机发送给所有的 writeHost
    • switchType

      • 是否允许读操作在 readHost 和 writeHost 上自动切换
      • 解决延迟问题,当从 readHost 上读取数据出现网络延迟等问题,自动从 writeHost 中读取
      • -1 不允许
      • 1 默认,允许
      • 2 根据主从同步状态,自动选择是否切换
        • 主从之间持续发送心跳
        • 心跳检测机制发送 IO 延迟,则 readHost 自动切换到 writeHost
        • 需要将 标签值设置为 show slave status
        • 推荐

          rule.xml

          ```java id mod-long
      autopartition-long.txt
<a name="PZTWT"></a>
## 准备数据
```java
use mydb01;
create table student(id int(4), name varchar(10));

use mydb01;
create table student(id int(4), name varchar(10));
  • 确保主从 mysql 中都存在 mydb01 和 mydb02 数据库
  • 结构
    • mycat
      • 192.168.2.129
    • 主 mysql
      • 192.168.2.2
    • 从 mysql
      • 192.168.2.128
  • 操作 Mycat

    • SQL 92 语法严格的 SQL
    • SQL 99 语法较为宽松
    • MyCat 采用 SQL 92
    • 操作端口 8066
    • 管理端口 9066

      验证读写分离

  • 开启

    • bin/mycat start
  • 查看状态
    • bin/mycat status
  • 登录
    • 需要借助已经安装 mysql 的计算机上远程登录
    • mysql -uroot -proot -h192.168.2.129 -P8066

      在 mycat 中写入,在 writeHost 中查看

/* mycat  */
use mydb;
insert into student(id, name) values(1, 'zs');

/* master */
use mydb01;
select * from student;
use mydb02;
select * from student;

错误调试

  • 错误日志
    • mycat/logs
      • mycat.log 执行出错
      • wrapper.log 启动错误
  • 常见错误 Invalid DataSource

    • 防火墙
    • IP
    • 端口
    • 权限问题
      • 在学习环境可以临时放开所有权限

        7. 使用 haproxy 实现 mycat 高可用

  • 在 bigdata03 上再次搭建一个 mycat

    • 复制 3 个配置文件即可
      • server.xml
      • schema.xml
      • rule.xml

        搭建 haproxy

  • 选择 bigdata04 虚拟机

  • 安装命令
    • yum -y install haproxy.x86_64
  • 授权
    • chown -R haproxy: haproxy /etc/haproxy
  • 配置文件
    • vi /etc/rsyslog.conf
    • 放开注释
      • $ModLoad imudp
      • $UDPServerRun 514
    • 设置日志文件路径
      • local2.* var/log/haproxy.log
      • 日志文件名和配置的保持一致
      • 重启日志服务
        • systemctl restart rsyslog.service

          配置 haproxy.cfg

          配置前端 frontend

          ```java frontend mycat

          操作端口

          bind 0.0.0:8066

          管理端口

          bind 0.0.0:9066

          连接方式

          mode tcp

          全局日志

          log global

          默认后端服务

          default_backend mycat_server
<a name="yfvZA"></a>
### 配置后端
```java
# 配置 server
backend mycat_server
# 负载均衡 分流算法
balance roundrobin

# mycat 所在操作节点
# check 为可选项,后面是间隔时间
server  mycat1 192.168.2.129:8066 check inter 5s rise 2 fall 3
server  mycat2 192.168.2.130:8066 check inter 5s rise 2 fall 3

# mycat 所在管理节点
server  mycatadmin1 192.168.2.129:8066 check inter 5s rise 2 fall 3
server  mycatadmin2 192.168.2.130:8066 check inter 5s rise 2 fall 3

# 监听状态
listen stats

# 模式
mode http

# 绑定端口
bing 0.0.0.0:5000

# 开启状态
stats enable
# 隐藏版本号
stats hide-version
# 设置可以通过网址访问
stats uri /haproxy
# 静态资源
stats realm Haproxy\ Statistics
# 通过网址访问时的登录名和密码
stats auth admin:admin
# 确保登录成功
stats admin if TRUE

配置默认值 stats

# 修改默认值
defaults
mode tcp
log global
option tcplog

启动并使用

  • 启动
    • systemctl start haproxy.service
  • 查看状态
    • systemctl status haproxy.service
  • 错误
    • cannot bind socket
    • 解决方法,关闭 selinux 防火墙
      • setenforce 0
  • 通过网址访问查看状态

    • 192.168.2.131:5000/haproxy#mycat_server/mycat1

      搭建第二个 haproxy

  • bigdata05

  • 与第一个配置方式相同

    8. 使用 keepalived 实现心跳机制与虚拟 IP

    keepalived

    安装

  • 查看版本号

    • keepalived.x86_64^C
    • yum -y install keepalived.x86_64

      编辑配置文件

  • vi /etc/keepalived/keepalived.conf ```java global_defs{ router_id NodeA }

vrrp_instance VI_1{ state MASTER # 设置主服务器 interface ens33 # 系统网卡名称 virtual_router_id 10 # 多个 haproxy 节点保持一致 priority 100 # 权重,多个节点数字越大,权重越高 authentication{ auth_type PASS auth_pass 1234 # 多个 haproxy 节点保持一致 } virtual_ipaddress{ 192.168.2.222/24 # 24 是网络位数,多个 haproxy 节点,虚拟 IP 保持一致 } track_script{ chk_haproxy # 追踪脚本的名称 } }

vrrp_script chk_haproxy{ script “/etc/check_haproxy.sh” interval 4 # 间隔,4 秒追踪一次 weight 3 # 权重 }

<a name="l5UpN"></a>
### check_haproxy 脚本
```java
A=`ps -C haproxy --no-header |wc -l`
if[$A -eq 0];then
systemctl start haproxy.service
fi

配置第二台 haproxy 节点的 keepalived

global_defs{
    router_id NodeB # 更改 id
}

vrrp_instance VI_1{
    priority 90 # 更改优先级
}
  • 修改两处,其他配置保持一致

    9. 演示 mysql 主从 Mycat 读写分离分库分表和 haproxy 及虚拟 Ip

    使用 keepalived

  • 启动

    • systemctl start keepalived.service
  • 开机自动启
    • systemctl enable keepalived.service
  • 重启
    • systemctl restart keepalived.service
  • 查看状态
    • systemctl status keepalived.service
  • 查看虚拟 IP 被哪个节点使用

    • ip a
    • 多个节点存活时,虚拟 IP 分配给权重最大的节点
    • 宕机的节点复活后,如果权限高,仍然会重新占用虚拟 IP

      访问

  • windows 模拟客户端访问

    • mysql -uroot -proot h192.168.2.222 -P8066
    • 实际应用中,只有 192.168.2.222 对客户可见
  • 访问路径

    • 192.168.2.222(keepalived 虚拟 IP)—>haproxy—>MyCat1/MyCat2—>MySQL主从

      架构

  • 互为主从

    • master 和 slave 互为主从
  • 级联主从
    • slave 是另一个 slave 的 master