mysql 主从 Mycat读写分离 实践

mysql 主从 Mycat读写分离 实践

 

 M1 my.cnf:

[mysqld]
server-id = 1
log-bin = M1-log-bin
gtid_mode=ON
enforce-gtid-consistency=ON #服务器通过允许仅执行可以使用 GTID 安全记录的语句来实现 GTID 一致性

M2 my.cnf:

[mysqld]
server-id = 2
log-bin = M2-log-bin
gtid_mode=ON
enforce-gtid-consistency=ON 

S1 my.cnf:

[mysqld]
server-id = 3
gtid_mode=ON
enforce-gtid-consistency=ON 

schema.xml:

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
        <schema name="test" checkSQLschema="true" sqlMaxLimit="100" randomDataNode="test01" dataNode="test01"></schema> <!--逻辑库-->
        <dataNode name="test01" dataHost="mall" database="test"></dataNode> <!--分片节点-->
        <dataHost name="mall" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100"> <!--节点主机-->
                <heartbeat>show slave status</heartbeat>
                <writeHost host="M1" url="192.168.3.102:3306" user="root" password="root">
                        <readHost host="S1" url="192.168.3.102:3308" user="root" password="root"></readHost>
                </writeHost>
                <writeHost host="M2" url="192.168.3.102:3307" user="root" password="root"></writeHost>
        </dataHost>
</mycat:schema>

server.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:server SYSTEM "server.dtd">
<mycat:server xmlns:mycat="http://io.mycat/">
    <system>
    <property name="nonePasswordLogin">0</property>
    <property name="ignoreUnknownCommand">0</property>
    <property name="useHandshakeV10">1</property>
    <property name="removeGraveAccent">1</property>
    <property name="useSqlStat">0</property> 
    <property name="useGlobleTableCheck">0</property> 
        <property name="sqlExecuteTimeout">300</property>
        <property name="sequnceHandlerType">1</property>
        <property name="sequnceHandlerPattern">(?:(\s*next\s+value\s+for\s*MYCATSEQ_(\w+))(,|\)|\s)*)+</property>
    <property name="subqueryRelationshipCheck">false</property> 
    <property name="sequenceHanlderClass">io.mycat.route.sequence.handler.HttpIncrSequenceHandler</property>
        <property name="processorBufferPoolType">0</property>
    <property name="serverPort">8066</property> 
    <property name="managerPort">9066</property> 
    <property name="bindIp">0.0.0.0</property>
        <property name="handleDistributedTransactions">0</property>
        <property name="useOffHeapForMerge">0</property>
        <property name="memoryPageSize">64k</property>
        <property name="spillsFileBufferSize">1k</property>
        <property name="useStreamOutput">0</property>
        <property name="systemReserveMemorySize">384m</property>
        <property name="useZKSwitch">false</property>
        <property name="strictTxIsolation">false</property>
        <property name="useZKSwitch">true</property>
        <property name="parallExecute">0</property>
    </system>
    <!--上面都是默认配置文件只修改了<user>标签内容--> <user name="root" defaultAccount="true"> <!--用户和权限--> <property name="password">root</property> <!--密码--> <property name="schemas">test</property> <!--可访问的逻辑库--> <property name="defaultSchema">test</property><!--默认逻辑库--> </user> </mycat:server>

docker-compose.yml:

version: "3.9"
services:

  mysql-M1:
    image: mysql:5.7
    container_name: mysql-M1
    environment:
      - MYSQL_ROOT_PASSWORD=root
    ports:
      - '3306:3306'
    volumes:
      - /db/mysql-M1/data:/var/lib/mysql
      - /db/mysql-M1/conf:/etc/mysql/conf.d

  mysql-M2:
    image: mysql:5.7
    container_name: mysql-M2
    environment:
      - MYSQL_ROOT_PASSWORD=root
    ports:
      - '3307:3306'
    volumes:
      - /db/mysql-M2/data:/var/lib/mysql
      - /db/mysql-M2/conf:/etc/mysql/conf.d

  mysql-S1:
    image: mysql:5.7
    container_name: mysql-S1
    environment:
      - MYSQL_ROOT_PASSWORD=root
    ports:
      - '3308:3306'
    volumes:
      - /db/mysql-S1/data:/var/lib/mysql
      - /db/mysql-S1/conf:/etc/mysql/conf.d

  mycat-01:
    image: mycat:1.6.7.6
    container_name: mycat-01
    ports:
      - '8066:8066'
      - '9066:9066'
    volumes:
      - /db/mycat-01/log:/usr/local/mycat/logs
      - /db/mycat-01/conf:/usr/local/mycat/conf

  mycat-02:
    image: mycat:1.6.7.6
    container_name: mycat-02
    ports:
      - '8067:8066'
      - '9067:9066'
    volumes:
      - /db/mycat-02/log:/usr/local/mycat/logs
      - /db/mycat-02/conf:/usr/local/mycat/conf

#启动前先放置好mysql和mycat的配置文件  启动执行以下命令:

docker-compose up -d

查看:#基于二进制的话就要记下“File”和"Position" 供后续使用

mysql 主从 Mycat读写分离 实践

 

 

 

创建用于复制的用户:

mysql> CREATE USER 'repl'@'%.example.com' IDENTIFIED BY 'password';
mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%.example.com';

此案例使用的是下面用户和权限
CREATE USER 'root'@'%' IDENTIFIED BY 'root';
GRANT ALL ON *.* TO 'root'@'%';

在从节点执行 更改主声明

#基于GITD

CHANGE MASTER TO MASTER_HOST='IP',MASTER_USER='账号',MASTER_PASSWORD='密码',MASTER_PORT=端口,MASTER_AUTO_POSITION=1;

#基于二进制

CHANGE MASTER TO MASTER_HOST='IP',MASTER_USER='账号',MASTER_PASSWORD='密码',MASTER_PORT=端口 MASTER_LOG_POS = 位置,MASTER_LOG_FILE = '二进制文件名 ';

检查:双YES即可

mysql 主从 Mycat读写分离 实践

 

 

 分别M1 M2互为主从 S1为M1的从操作

有可能需要用到的命令

START SLAVE;    #启动从
STOP SLAVE;     #停从
reset slave all;   #重置从
SHOW SLAVE STATUS \G  #查看从状态
RESET MASTER; #重置主

验证:


登录【主服务器】
mysql> CREATE DATABASE test; #创建test数据库 mysql> USE test; #进库
CREATE TABLE `user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,
  `age` tinyint(3) unsigned NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;  #创建user表
INSERT INTO user (id, name, age) VALUES (2, 'zhangsan', 18); #插数据
SELECT * FROM user; 查看
mysql 主从 Mycat读写分离 实践

 

 

登录 【从服务器】查看有没有即可

use test;
SELECT * FROM user;

 

--------------------------------------------------------------------------------------------

mycat

制作镜像 可参考官网

cd /db
tar -zxvf mycat1.6.7.6.tar.gz -C /db/ mycat/conf
mv mycat mycat-01
cp -r  mycat-01 mycat-02
编辑或替换成启动配置文件
mycat01和mycat-02配置一样的

因记录搭建实践所以还修改了wrapper.conf调低资源消耗
wrapper.java.additional.9=-Xmx512M
wrapper.java.additional.10=-Xms256M

--------------------------------------------------------------------------------------------

keepalived+LVS

主  keepalived.conf

! Configuration File for keepalived

global_defs {
   router_id lvs01
   vrrp_skip_check_adv_addr
}
vrrp_instance API {
    state MASTER
    interface ens32
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.3.200/24
    }
    notify_master "/etc/keepalived/notify.sh master"
    notify_backup "/etc/keepalived/notify.sh backup"
    notify_fault  "/etc/keepalived/notify.sh fault"
}
virtual_server 192.168.3.200 8066 {
    delay_loop 6
    lb_algo rr
    lb_kind DR
    persistence_timeout 50
    protocol TCP
    real_server 192.168.3.102 8066 {
        weight 1
        TCP_CHECK {
                connect_timeout 10  
                retry 3             
                delay_before_retry 3
                connect_port 8066
            }
        }
    real_server 192.168.3.102 8067 {
        weight 1
        TCP_CHECK {
                connect_timeout 10  
                retry 3             
                delay_before_retry 3
                connect_port 8067
            }
        }
}

备  keepalived.conf:

! Configuration File for keepalived

global_defs {
   router_id lvs02
   vrrp_skip_check_adv_addr
}
vrrp_instance API {
    state BACKUP
    interface ens32
    virtual_router_id 51
    priority 50
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.3.200/24
    }
    notify_master "/etc/keepalived/notify.sh master"
    notify_backup "/etc/keepalived/notify.sh backup"
    notify_fault  "/etc/keepalived/notify.sh fault"
}
virtual_server 192.168.3.200 8066 {
    delay_loop 6
    lb_algo rr
    lb_kind DR
    persistence_timeout 50
    protocol TCP
    real_server 192.168.3.102 8066 {
        weight 1
        TCP_CHECK {
                connect_timeout 10  
                retry 3             
                delay_before_retry 3
                connect_port 8066
            }
        }
    real_server 192.168.3.102 8067 {
        weight 1
        TCP_CHECK {
                connect_timeout 10  
                retry 3             
                delay_before_retry 3
                connect_port 8067
            }
        }
}

RS上使用的绑定VIP脚本 realserver.sh:

#!/bin/bash
#description: Config realserver

VIP=192.168.3.200

 
case "$1" in
start)
       /sbin/ifconfig lo:0 $VIP netmask 255.255.255.255 broadcast $VIP
       /sbin/route add -host $VIP dev lo:0
       echo "1" >/proc/sys/net/ipv4/conf/lo/arp_ignore
       echo "2" >/proc/sys/net/ipv4/conf/lo/arp_announce
       echo "1" >/proc/sys/net/ipv4/conf/all/arp_ignore
       echo "2" >/proc/sys/net/ipv4/conf/all/arp_announce
       sysctl -p >/dev/null 2>&1
       echo "RealServer Start OK"
       ;;
stop)
       /sbin/ifconfig lo:0 down
       /sbin/route del $VIP >/dev/null 2>&1
       echo "0" >/proc/sys/net/ipv4/conf/lo/arp_ignore
       echo "0" >/proc/sys/net/ipv4/conf/lo/arp_announce
       echo "0" >/proc/sys/net/ipv4/conf/all/arp_ignore
       echo "0" >/proc/sys/net/ipv4/conf/all/arp_announce
       echo "RealServer Stoped"
       ;;
*)
       echo "Usage: $0 {start|stop}"
       exit 1
esac
 
exit 0

主备切换通知邮件脚本 notify.sh: 前提需要配下mail.rc才发的出去

#!/bin/bash
#
contact='502369651@qq.com'
notify() {
local mailsubject="$(hostname) to be $1, vip floating"
local mailbody="$(date +'%F %T'): vrrp transition, $(hostname) changed to be $1"
echo "$mailbody" | mail -s "$mailsubject" $contact
}

case $1 in
master)
        notify master
        ;;
backup)
        notify backup
        ;;
fault)
        notify fault
        ;;
*)
        echo "Usage: $(basename $0) {master|backup|fault}"
        exit 1
        ;;
esac

mail.rc:

#vim /etc/mail.rc #添加如下内容
set from=xxxx@126.com
set smtp=smtp.126.com
set smtp-auth-user=xx@126.com
set smtp-auth-password=xxx
set smtp-auth=login
#---说明
#from:对方收到邮件时显示的发件人
#smtp:指定第三方发邮件的smtp服务器地址
#set smtp-auth-user:第三方发邮件的用户名
#set smtp-auth-password:用户名对应的密码,有些邮箱填的是授权码
#smtp-auth:SMTP的认证方式,默认是login,也可以改成CRAM-MD5或PLAIN方式

看看效果启备再启主;启动命令:systemctl start keepalived.service

mysql 主从 Mycat读写分离 实践

 

 还可以通过 ip a 查看VIP在谁那

测试:通过VIP进入

mysql 主从 Mycat读写分离 实践

 

 

这样整体就完成了mysql+mycat+keepalived+LVS的高可用负载均衡读写分离的方案

--------------------------------------------------------------

 

上一篇:MyCat分库分表--实战10--多节点扩容与多节点删除


下一篇:快速学习-Mycat 注解