• MaxScale


    Maxscale介绍

    MaxScale是maridb开发的一个mysql数据中间件,其配置简单,能够实现读写分离,并且可以根据主从状态实现写库的自动切换。

    注:MaxScale需要MariaDB至少 10.3.1 以上版本的支持,版本过低可能导致部分功能无法使用。

    MariaDB MaxScale 2.2版本,在支持原有读写分离的基础上,又添加了主从复制集群管理功能,

    MariaDB MaxScale 2.5版本,实现了GUI图形化、可视化监控管理web页面。


    功能概述

    Mariadbmon守护进程,会实时探测主从复制状态,可以通过执行故障转移,在线切换和重新加入来修改复制群集。

    1)Failover:用最新的slave替换发生故障的master,故障转移分为Manual Failover和Automatic Failover。在当前已存在的主从复制环境中,MaxScale可以监控master主机故障,并且故障自动转移。

    需要把loss-less无损半同步复制(semi replication)开启,参数rpl_semi_sync_master_wait_point=AFTER_SYNC,确保slave已经接收到了master的binlog,因为master宕机,MaxScale无法远程拷贝scp那一缺失的binlog,那么数据就出现不一致了。

    2)Switchover:在线主从切换,类似MHA的masterha_master_switch --master_state=alive。

    如果机器需要维护,将master角色在线切换到其他主机上(例如更换原master坏掉的硬盘),这并不是master进程崩溃引起的故障转移。在线切换通常在0.5-2秒左右,并且会阻塞写(在原master上执行SET GLOBAL read_only=1命令设置全局只读,且执行FLUSH TABLES把所有的表强制关闭),建议在凌晨业务低峰期执行在线切换。

    3)Rejoin:重新加入到新集群作为slave,即死掉的原master如何与提升为新的master建立同步复制关系?由于Maxscale是基于GTID模式的主从复制,全局事务号是唯一的,会自动执行CHANGE MASTER TO NEW_MASTER, MASTER_USE_GTID = current_pos命令,无需人工参与。

    (请确保所有MySQL主从节点参数log_slave_updates=ON开启。)

    (注意!Failover以及Switchover和Rejoin仅支持基于GTID的复制一起使用,并且仅适用于简单的一主多从拓扑架构:即1个master后面跟着多个slave。)


    Maxscale架构搭建

    实现主从复制,读写分离和自动化故障转移

    实验环境

    操作系统: CentOS 7.6

    数据库: mariadb 10.5.5

    数据库代理: maxscale 2.5.4

    Maxsclae:172.16.1.51,端口:3306

    Master:172.16.1.51,端口:63132

    Slave1:172.16.1.41,端口:63132

    Slave2:172.16.1.31,端口:63132

    集群网络架构图

    集群网络架构图

    MariaDB主从复制

    MariaDB主从复制是通过二进制日志文件实现,在主服务器上完成所有的写入操作,通过二进制日志文件,将数据库改动发送给从服务器。从服务器接受到的二进制日志文件,会转储为relay log(中继日志),然会再在数据库中重建。
    同时需要注意,主从复制集群具有单向性,在从服务器进行的任何写入操作将不会同步至主服务器上。这个问题将通过 MaxScale 的读写分离模块来解决。
    还有一个不在本文范围的问题,当有多太主服务器时,将会涉及到数据同步问题,很多公司耗费了大量的人力物力都没法完全解决的文件,MariaDB 支持Galera 集群,这是一个高可用的解决方案,虽然降低了服务器性能,但是保证数据的一致性,可以用在读取性能要求大于写入性能的地方。


    主服务器配置

    设置主服务器(172.16.1.51)配置文件

    [root@db01 ~]# cat > /etc/my.cnf.d/mysql-clients.cnf <<EOF
    #
    # These groups are read by MariaDB command-line tools
    # Use it for options that affect only one utility
    #
    
    [mysql]
    
    [mysql_upgrade]
    
    [mysqladmin]
    
    [mysqlbinlog]
    
    [mysqlcheck]
    
    [mysqldump]
    
    [mysqlimport]
    
    [mysqlshow]
    
    [mysqlslap]
    
    [mysqld]
    # 指定全局唯一服务器ID,ID 可以为 1~65536 的任意一个。
    server-id=100
    
    # 指定二进制日志文件名称,同时会开启二进制日志文件
    # 默认MariaDB使用的是混合二进制日志文件,也就是命令和二进制的数据库改动将都将记录到二进制日志中
    log-bin=bin-log 
    
    # 指定二进制日志文件的索引位置
    log-bin-index=bin-log.index 
    # 注意,以上两个配置指定的文件路径都是基于 datadir 配置的
    
    # 指定服务器的监听端口
    # 这里我会将MaxScale配置监听在3306端口上,所以需要修改MariaDB的默认监听端口
    # 如果开启了SELinux,需要配置监听在规定的特殊端口上,如果没有则忽略。
    # SELinux规定的监听端口为:1186,3306,63132-63164
    port=63132
    
    # 只保留 30 天内的日志
    expire_logs_days=30
    
    # 二进制日志文件格式
    binlog-format=ROW
    # ROW格式下日志的级别
    binlog-row-image=minimal
    # 此两项为打开从服务器崩溃二进制日志功能,信息记录在事务表而不是保存在文件
    master-info-repository=TABLE
    relay-log-info-repository=TABLE
    
    innodb_log_file_size=30M
    innodb_log_buffer_size=512M
    innodb_strict_mode=0
    EOF
    

    如果开启防火墙,配置防火墙规则

    firewall-cmd --add-port=63132/tcp --permanent
    firewall-cmd --reload
    

    启动主服务器

    systemctl start mariadb
    systemctl enable mariadb
    

    设置密码,更新,进入MariaDB

    [root@nfs ~]# mysqladmin password 123
    [root@nfs ~]# mysql_upgrade -u root -p 123
    Enter password: 123
    [root@nfs ~]# mysql -uroot -p123
    

    添加用户

    # 监视账户
    create user maxscale_monitor@'%' identified by "123456";
    GRANT REPLICATION slave,replication client on *.* to maxscale_monitor@'%';
    GRANT SUPER, RELOAD on *.* to 'maxscale_monitor'@'%';
    
    # 路由账户用于用户认证
    create user maxscale_route@'%' identified by "123456";
    GRANT SELECT ON mysql.* TO maxscale_route@'%';
    GRANT SHOW DATABASES ON *.* TO maxscale_route@'%';
    
    # 如果主服务器和管理机是一个, 添加这一用户
    GRANT ALL PRIVILEGES ON *.* TO 'maxscale_monitor'@'db01' IDENTIFIED BY '123456' WITH GRANT OPTION;
    GRANT REPLICATION slave,replication client on *.* to maxscale_monitor@'db01';
    GRANT SUPER, RELOAD on *.* to 'maxscale_monitor'@'db01';
    GRANT ALL PRIVILEGES ON *.* TO 'maxscale_route'@'db01' IDENTIFIED BY '123456' WITH GRANT OPTION;
    GRANT SELECT ON mysql.* TO maxscale_route@'db01';
    GRANT SHOW DATABASES ON *.* TO maxscale_route@'db01';
    
    # 刷新
    flush privileges;
    

    从服务器配置

    设置从服务器(172.16.1.31和172.16.1.41)配置文件

    [root@nfs ~]# cat > /etc/my.cnf.d/mysql-clients.cnf <<EOF
    #
    # These groups are read by MariaDB command-line tools
    # Use it for options that affect only one utility
    #
    
    [mysql]
    
    [mysql_upgrade]
    
    [mysqladmin]
    
    [mysqlbinlog]
    
    [mysqlcheck]
    
    [mysqldump]
    
    [mysqlimport]
    
    [mysqlshow]
    
    [mysqlslap]
    
    [mysqld]
    # 注意,服务器ID必须为全局唯一
    server-id=200
    
    log-bin=bin-log 
    log-bin-index=bin-log.index 
    
    # 配置将中继日志文件转储至relay-log中
    # 可以不配置中继日志,当服务器以从模式运行时,将会自动开启
    relay-log=relay-log
    # 指定 relay 日志的索引文件。
    relay-log-index=relay-log.index
    # 指定从服务器默认为只读模式,禁止任何写入操作
    read-only=ON
    # 只保留 30 天内的日志
    expire_logs_days=30
    port=63132
    
    innodb_log_file_size=30M
    innodb_log_buffer_size=512M
    innodb_strict_mode=0
    EOF
    
    [root@backup ~]# cat > /etc/my.cnf.d/mysql-clients.cnf <<EOF
    #
    # These groups are read by MariaDB command-line tools
    # Use it for options that affect only one utility
    #
    
    [mysql]
    
    [mysql_upgrade]
    
    [mysqladmin]
    
    [mysqlbinlog]
    
    [mysqlcheck]
    
    [mysqldump]
    
    [mysqlimport]
    
    [mysqlshow]
    
    [mysqlslap]
    
    [mysqld]
    # 注意,服务器ID必须为全局唯一
    server-id=300
    
    log-bin=bin-log 
    log-bin-index=bin-log.index 
    
    # 配置将中继日志文件转储至relay-log中
    # 可以不配置中继日志,当服务器以从模式运行时,将会自动开启
    relay-log=relay-log
    # 指定 relay 日志的索引文件。
    relay-log-index=relay-log.index
    # 指定从服务器默认为只读模式,禁止任何写入操作
    read-only=ON
    # 只保留 30 天内的日志
    expire_logs_days=30
    port=63132
    
    innodb_log_file_size=30M
    innodb_log_buffer_size=512M
    innodb_strict_mode=0
    EOF
    

    如果开启防火墙,配置防火墙规则

    firewall-cmd --add-port=63132/tcp --permanent
    firewall-cmd --reload
    

    启动从服务器

    systemctl start mariadb
    systemctl enable mariadb
    

    设置密码,更新,进入MariaDB

    [root@nfs ~]# mysqladmin password 123
    [root@nfs ~]# mysql_upgrade -u root -p 123
    Enter password: 123
    [root@nfs ~]# mysql -uroot -p123
    

    添加用户

    # 监视账户
    create user maxscale_monitor@'172.16.1.%' identified by "123456";
    grant replication slave,replication client on *.* to maxscale_monitor@'172.16.1.%';
    GRANT SUPER, RELOAD on *.* to 'maxscale_monitor'@'172.16.1.%';
    # 路由账户
    create user maxscale_route@'172.16.1.%' identified by "123456";
    GRANT SELECT ON mysql.* TO maxscale_route@'172.16.1.%';
    GRANT SHOW DATABASES ON *.* TO maxscale_route@'172.16.1.%';
    
    GRANT SELECT ON mysql.* TO root@'%';
    GRANT SHOW DATABASES ON *.* TO root@'%';
    
    # 刷新
    flush privileges;
    

    配置主服务器(172.16.1.51)指向

    # 注意一定不要设置Master_Log_File,当主服务器切换记录二进制日志文件时,从服务器将无法切换到对应的文件。留空将会自动进行配置。
    CHANGE MASTER TO MASTER_HOST='172.16.1.51', MASTER_PORT=63132, MASTER_USER='maxscale_monitor', MASTER_PASSWORD='123456', MASTER_USE_GTID=current_pos;
    

    启动从状态

    MariaDB [(none)]> START SLAVE;
    

    查询从节点状态信息

    MariaDB [(none)]> SHOW SLAVE STATUSG
    *************************** 1. row ***************************
                    Slave_IO_State: Waiting for master to send event
                       Master_Host: 172.16.1.51
                       Master_User: maxscale_monitor
                       Master_Port: 63132
                     Connect_Retry: 60
                   Master_Log_File: bin-log.000001
               Read_Master_Log_Pos: 326
                    Relay_Log_File: relay-log.000002
                     Relay_Log_Pos: 623
             Relay_Master_Log_File: bin-log.000001
                  Slave_IO_Running: Yes
                 Slave_SQL_Running: Yes
                   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: 326
                   Relay_Log_Space: 926
                   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: 0
     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: 100
                    Master_SSL_Crl: 
                Master_SSL_Crlpath: 
                        Using_Gtid: Current_Pos
                       Gtid_IO_Pos: 0-200-2970
           Replicate_Do_Domain_Ids: 
       Replicate_Ignore_Domain_Ids: 
                     Parallel_Mode: optimistic
                         SQL_Delay: 0
               SQL_Remaining_Delay: NULL
           Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
                  Slave_DDL_Groups: 0
    Slave_Non_Transactional_Groups: 0
        Slave_Transactional_Groups: 0
    1 row in set (0.000 sec)
    

    管理机配置

    安装

    yum install libaio libaio-devel novacom-server libedit -y
    rpm -ivh https://dlm.mariadb.com/1160524/MaxScale/2.5.4/yum/centos/7/x86_64/maxscale-2.5.4-1.rhel.7.x86_64.rpm
    # 或者
    wget https://dlm.mariadb.com/1160524/MaxScale/2.5.4/yum/centos/7/x86_64/maxscale-2.5.4-1.rhel.7.x86_64.rpm
    yum -y install maxscale-2.5.4-1.rhel.7.x86_64.rpm
    

    配置文件

    [root@db01 ~]# cat > /etc/maxscale.cnf <<EOF
    # MaxScale documentation:
    # https://mariadb.com/kb/en/mariadb-maxscale-24/
    
    # Global parameters
    #
    # Complete list of configuration options:
    # https://mariadb.com/kb/en/mariadb-maxscale-24-mariadb-maxscale-configuration-guide/
    
    # 全局模块
    [maxscale]
    # 开启线程个数,默认为1.设置为auto会同cpu核数相同
    threads=auto
    # timestamp精度
    ms_timestamp=1
    # 记录info
    log_info=1
    # 日志递增
    log_augmentation=1
    # 打开GUI图形管理页面
    admin_host=0.0.0.0
    # 不设置HTTPS服务
    admin_secure_gui=false
    
    # Server definitions
    #
    # Set the address of the server to the network
    # address of a MariaDB server.
    #
    
    # 主机模块
    [server1]
    type=server
    # 指定服务器的unix socket路径
    # 如果 MaxScale 和 MariaDB 在同一台主机上,可以使用这种方法连接
    # 注意,socket 与 address/port 冲突,只能选其一。
    # 同时需要注意 MariaDB 的权限配置。
    #socket=/var/lib/mysql/mysql.sock 
    address=172.16.1.51
    port=63132
    protocol=MariaDBBackend
    
    [server2]
    type=server
    address=172.16.1.41
    port=63132
    protocol=MariaDBBackend
    
    [server3]
    type=server
    address=172.16.1.31
    port=63132
    protocol=MariaDBBackend
    
    # Monitor for the servers
    #
    # This will keep MaxScale aware of the state of the servers.
    # MariaDB Monitor documentation:
    # https://mariadb.com/kb/en/mariadb-maxscale-24-mariadb-monitor/
    
    # 故障转移监控模块
    [MariaDB-Monitor]
    type=monitor
    # 核心监控模块
    module=mariadbmon
    servers=server1,server2,server3
    user=maxscale_monitor
    password=123456
    # 每隔2秒探测一次
    monitor_interval=2000
    # 打开自动故障转移
    auto_failover=true
    # 打开自动重新加入
    auto_rejoin=true
    # slave 全部失效时 master 支撑全部请求
    detect_stale_master=true
    
    # Service definitions
    #
    # Service Definition for a read-only service and
    # a read/write splitting service.
    
    # ReadWriteSplit documentation:
    # https://mariadb.com/kb/en/mariadb-maxscale-24-readwritesplit/
    
    # 服务模块
    # 读写分离,基于statement SQL解析的方式
    [Read-Write-Service]
    type=service
    router=readwritesplit
    router_options=master,slave
    servers=server1,server2,server3
    # 默认禁止root用户访问,设置为1开启
    enable_root_user=1
    # 路由账号用于读写分离
    user=maxscale_route
    password=123456
    # 当主服务器挂了时,客户端的写入操作将会返回错误,服务器以只读模式运行。
    # 如果没有设置此值,那么当客户端执行写入操作时,MaxScale将会直接断开连接。
    master_failure_mode=error_on_write
    # 配合上一个选项取消只读模式,客户端的写入请求将会被重新处理。
    master_reconnection=true
    
    # 默认读是不被路由到master,设置为true允许master用于读取
    #master_accept_reads=true
    # 设置路由器会话随时使用的最大从站数量
    #max_slave_connections=2
    #auth_all_servers=true
    # 身份验证失败和警告的日志记录,记录那些试图连接到MaxScale和来自哪里
    #log_auth_warnings=true 
    # 强制select走master
    #filters=Hint  
    #允许slave落后master多少秒
    #max_slave_replication_lag=3600
    
    # Listener definitions for the services
    #
    # These listeners represent the ports the
    # services will listen on.
    #
    
    [Read-Write-Listener]
    type=listener
    service=Read-Write-Service
    protocol=MariaDBClient
    # 一定要指定!! 默认绑定IPv6
    address=0.0.0.0
    port=3306
    EOF
    

    启动

    systemctl start maxscale
    systemctl enable maxscale
    

    错误日志

    tailf /var/log/maxscale/maxscale.log
    

    使用MaxCtrl检查MaxScale状态

    [root@db01 ~]# maxctrl list services
    ┌────────────────────┬────────────────┬─────────────┬───────────────────┬───────────────────────────┐
    │ Service            │ Router         │ Connections │ Total Connections │ Servers                   │
    ├────────────────────┼────────────────┼─────────────┼───────────────────┼───────────────────────────┤
    │ Read-Write-Service │ readwritesplit │ 1           │ 1                 │ server1, server2, server3 │
    └────────────────────┴────────────────┴─────────────┴───────────────────┴───────────────────────────┘
    [root@db01 ~]# maxctrl list servers
    ┌─────────┬─────────────┬───────┬─────────────┬─────────────────┬──────┐
    │ Server  │ Address     │ Port  │ Connections │ State           │ GTID │
    ├─────────┼─────────────┼───────┼─────────────┼─────────────────┼──────┤
    │ server1 │ 172.16.1.51 │ 63132 │ 1           │ Master, Running │      │
    ├─────────┼─────────────┼───────┼─────────────┼─────────────────┼──────┤
    │ server2 │ 172.16.1.41 │ 63132 │ 1           │ Slave, Running  │      │
    ├─────────┼─────────────┼───────┼─────────────┼─────────────────┼──────┤
    │ server3 │ 172.16.1.31 │ 63132 │ 1           │ Slave, Running  │      │
    └─────────┴─────────────┴───────┴─────────────┴─────────────────┴──────┘
    [root@db01 ~]# maxctrl list listeners Read-Write-Service
    ┌─────────────────────┬──────┬──────┬─────────┬────────────────────┐
    │ Name                │ Port │ Host │ State   │ Service            │
    ├─────────────────────┼──────┼──────┼─────────┼────────────────────┤
    │ Read-Write-Listener │ 3306 │ ::   │ Running │ Read-Write-Service │
    └─────────────────────┴──────┴──────┴─────────┴────────────────────┘
    

    查看主从复制集群状态信息

    maxctrl list services
    

    image-20201008172021372

    查看服务状态信息

    maxctrl list servers
    

    image-20201008172032639

    查看服务监听状态信息

    maxctrl list listeners Read-Write-Service
    

    image-20201008172044403

    通过GUI WEB图形页面访问http://172.16.1.51:8989查看,登录名admin,密码mariadb:

    image-20201010201025497

    主从复制测试

    读写分离测试

    1. 先在 master 上创建一个测试用户
    create user 'root'@'%' identified by '123';
    grant ALL PRIVILEGES on *.* to 'rtest'@'%';
    
    1. 使用 Mysql 客户端到连接 MaxScale
    mysql -uroot -p'123' -h'172.16.1.51' -P3306
    

    查看数据库服务器名确认当前所在数据库

    MariaDB [(none)]> Select @@hostname;
    +------------+
    | @@hostname |
    +------------+
    | nfs        |
    +------------+
    1 row in set (0.002 sec)
    
    MariaDB [(none)]> start transaction;
    Query OK, 0 rows affected (0.002 sec)
    
    MariaDB [(none)]> Select @@hostname;
    +------------+
    | @@hostname |
    +------------+
    | db01       |
    +------------+
    1 row in set (0.002 sec)
    
    MariaDB [(none)]> rollback;
    Query OK, 0 rows affected (0.002 sec)
    
    MariaDB [(none)]> Select @@hostname;
    +------------+
    | @@hostname |
    +------------+
    | backup     |
    +------------+
    1 row in set (0.002 sec)
    
    

    故障转移测试

    slave故障转移

    在 slave 发生故障时,MaxScale 可以自动识别出来,并移除路由列表,当故障恢复重新上线后,MaxScale 也能自动将其加入路由,过程透明。

    # 首先先检查以下服务器
    maxctrl list servers
    # 手动关闭主服务器
    systemctl stop mariadb
    # 再次查看服务器
    # 注意,这里需要稍微等待以下大概2~4秒,并不是立即生效的
    maxctrl list servers
    # 这里再重新启动服务器,看看是否会重新加入
    systemctl start mariadb
    # 注意,从服务器默认并没有设置 gtid_binlog_pos 值,当提升为主服务器时,此时其余的服务器
    # 并不会指向该服务器(也就是server2),需要在server2上提交一个事务才能生成 gtid_binlog_pos
    # 值,其余服务器才能将主服务器指向该 server2。如果 server2 已经设置了 gtid_binlog_pos
    # 那么将不会有这些问题。这里我们可以先查看以下服务器状态:
    maxctrl list servers
    # 当我们向 MaxScale 提交事务后,就可以正常使用了。
    mysql -uroot -p123 -P63132 -h172.16.1.41 -e'create table test (id int)' somata
    # 此时我们再查看server1服务器状态,它就会发生改变了
    # 同时我们也能发现,GTID也发送了改变
    maxctrl list servers
    # 如果有需求,可以使用命令将主服务器重新迁移回 server1
    maxctrl call command mariadbmon switchover MariaDB-Monitor server1 server2
    # 再次查看服务器
    maxctrl list servers
    

    场景一:Automatic Failover故障转移

    Failover细节:

    1)选择最新的slave作为master,依照以下顺序标准排列:

    1. gtid_IO_pos(中继日志中的最新事件)。
    2. gtid_current_pos(处理最多的事件)。
    3. log_slave_updates已开启。
    4. 磁盘空间不低。
    5. 如果以上条件都满足,按照maxscale.cnf主机模板的顺序进行故障转移,例如server2挂了,将切换到server3上,依次类推。

    2)如果最新的slave具有未处理的中继日志,会根据参数failover_timeout=90等待90秒,超过90秒数据未同步完,则关闭故障转移。通过判断gtid_binlog_pos和gtid_current_pos值是否相等。

    3)准备新的master

    ① 在最新的slave上,关闭复制进程执行命令:

    SET STATEMENT max_statement_time=1 FOR STOP SLAVE;
    

    并清空同步复制信息执行命令。

    SET STATEMENT max_statement_time=1 FOR RESET SLAVE ALL;
    

    ② 在最新的slave上,关闭只读read_only 执行命令。

    SET STATEMENT max_statement_time=1 FOR SET GLOBAL
    read_only=0
    

    ③ 在最新的slave上,启用EVENT事件(MySQL定时任务)。

    ④ 接收客户端读写请求。

    4)重定向所有slave指向新的master进行同步复制

    ① 停止同步复制,执行命令

    SET STATEMENT max_statement_time=1 FOR STOP SLAVE
    

    ② 指向新的master进行复制,执行命令

    SET STATEMENT
    
    max_statement_time=1 FOR CHANGE MASTER '' TO
    
    MASTER_HOST = '127.0.0.1', MASTER_PORT = 3314,
    
    MASTER_USE_GTID = current_pos, MASTER_USER = 'admin',
    
    MASTER_PASSWORD = '123456'
    

    ③ 开启同步复制,执行命令

    SET STATEMENT max_statement_time=1 FOR START SLAVE
    

    5)检查所有slave复制是否正常,执行命令SHOW ALL SLAVES STATUS判断Slave_IO_Running和Slave_SQL_Running值是否都为双Yes。

    场景二:Manual Failover故障转移

    通过以下命令可以实现手工故障切换:

    # maxctrl call command mariadbmon failover MariaDB-Monitor
    

    这里的切换细节跟自动故障转移是一样的

    场景三:Switchover在线平滑切换

    目前的主是server1,从是server2。

    通过以下命令可以实现在线切换:

    # maxctrl call command mariadbmon switchover MariaDB-Monitor server2 server1
    

    注:server2代表即将成为新的master,server1代表是原来旧的master。

    Switchover细节

    准备降级的旧master:

    1)在旧的master上,开启只读read_only 执行命令。

    SET STATEMENT max_statement_time=1 FOR SET GLOBAL
    

    read_only=1禁止数据写入。

    2)终止SUPER权限超级用户的连接,通过以下命令找到超级用户连接Id:

    SELECT DISTINCT * FROM (SELECT P.id,P.user FROM
    
    information_schema.PROCESSLIST as P INNER JOIN mysql.user
    
    as U ON (U.user = P.user) WHERE (U.Super_priv = 'Y' AND
    
    P.COMMAND != 'Binlog Dump' AND P.id != (SELECT
    
    CONNECTION_ID()))) as tmp;
    

    然后执行KILL命令,因为read_only只读不影响SUPER权限超级用户更改数据。

    3)执行FLUSH TABLES把所有表强制关闭。

    4)执行FLUSH LOGS刷新二进制日志,以便所有binlog都刷到磁盘上。

    5)在旧master上执行:SELECT @@gtid_current_pos, ,@@gtid_binlog_pos记录gtid事务号。

    在新master上执行:SELECT MASTER_GTID_WAIT('GTID');如果执行结果都为0,表示已经完成数据同步,可以进行下一步切换,否则需要一直等待完成。

    6)后面的步骤跟故障转移一样。

    MaxScale配置详解

    创建用户

    注意: 每个数据库上创建相同的帐户

    创建MaxScale用户帐户

    MaxScale检查传入的客户端是否有效。为此,MaxScale需要从后端数据库检索用户身份验证信息。为此,您可以在数据库集群的主服务器上执行以下SQL命令来创建一个特殊的用户帐户。

    CREATE USER 'maxscale'@'%' IDENTIFIED BY 'maxscale_password';
    GRANT SELECT ON mysql.user TO 'maxscale'@'%';
    GRANT SELECT ON mysql.db TO 'maxscale'@'%';
    GRANT SELECT ON mysql.tables_priv TO 'maxscale'@'%';
    GRANT SELECT ON mysql.columns_priv TO 'maxscale'@'%';
    GRANT SELECT ON mysql.proxies_priv TO 'maxscale'@'%';
    GRANT SELECT ON mysql.roles_mapping TO 'maxscale'@'%';
    GRANT SHOW DATABASES ON *.* TO 'maxscale'@'%';
    
    # 创建用于用户认证的用户
    CREATE USER 'maxscale'@'172.16.1.%' IDENTIFIED BY '123456';
    # 授权对 mysql 数据库的SELECT权限
    GRANT SELECT ON `mysql`.* TO 'maxscale'@'172.16.1.%';
    # 授予 SHOW DATABASES 权限
    GRANT SHOW DATABASES ON *.* TO 'maxscale'@'172.16.1.%';
    
    # 创建用于服务监控的用户
    CREATE USER 'maxscale_mon'@'172.16.1.%' IDENTIFIED BY '123456';
    # 给予复制权限,用于复制服务器状态类信息。
    GRANT REPLICATION CLIENT ON *.* TO 'maxscale_mon'@'172.16.1.%'; 
    

    创建客户用户帐户

    由于MariaDB MaxScale位于客户端和后端数据库之间,因此后端数据库将看到所有客户端,就好像它们是从MaxScale的地址进行连接一样。这通常意味着每个用户需要两组授予。

    例如,假设用户'jdoe'@'client-host'存在并且MaxScale位于 maxscale-host。如果'jdoe'@'client-host'需要能够通过MaxScale连接,则必须创建另一个用户'jdoe'@'maxscale-host'。第二个用户必须具有与'jdoe'@'client-host'相同的密码和相似的授权。

    最快的方法是首先创建新用户:

    CREATE USER 'jdoe'@'maxscale-host' IDENTIFIED BY 'my_secret_password';
    

    然后执行SHOW GRANTS查询:

    MariaDB [(none)]> SHOW GRANTS FOR 'jdoe'@'client-host';
    +-----------------------------------------------------------------------+
    | Grants for jdoe@client-host                                           |
    +-----------------------------------------------------------------------+
    | GRANT SELECT, INSERT, UPDATE, DELETE ON *.* TO 'jdoe'@'client-host'   |
    +-----------------------------------------------------------------------+
    1 row in set (0.01 sec)
    

    然后将相同的授权复制给'jdoe'@'maxscale-host'用户。

    GRANT SELECT, INSERT, UPDATE, DELETE ON *.* TO 'jdoe'@'maxscale-host';
    

    生成两个单独帐户的一种替代方法是使用一个具有通配符主机('jdoe'@'%')的帐户,该主机覆盖两个主机。这比拥有特定的用户帐户更为方便,但安全性较低,因为它允许所有主机进行访问。

    # 创建一个用户测试的用户。
    CREATE USER 'client'@'172.16.1.%' IDENTIFIED BY '123456';
    # 创建一个测试用数据库
    CREATE DATABASE somata;
    # 授权所有权限
    GRANT ALL ON somata.* TO 'client'@'172.16.1.%';
    

    密码加密

    主要是为了防止配置文件泄露导致密码暴露。

    创建密钥文件

    maxkeys
    

    密钥文件默认存放在/var/lib/maxscale/.secrets

    创建加密密码

    maxpasswd 123456
    

    注:如果不想在配置文件中使用加密的密码,则需要删除 .secrets 文件。

    配置文件参数详解:

    ① 故障转移监控模板

    [MariaDB-Monitor]

    auto_failover=true

    #打开自动故障转移,false为关闭,需要人工执行命令去做故障转移,通常为true。

    auto_rejoin=true

    #打开自动重新加入,false为关闭,需要人工执行CHANGE MASTER TO NEW_MASTER, MASTER_USE_GTID = current_pos命令,通常为true。

    failcount=3

    # 3次连接失败,认定主库down掉,开始启动故障转移,默认是5次尝试。

    failover_timeout=90

    # 假定slave库有延迟,在默认90秒时间内,没有同步完,自动关闭故障转移。通常默认值即可。

    switchover_timeout=90

    # 假定slave库有延迟,在默认90秒时间内,没有同步完,自动关闭在线切换。通常默认值即可。

    verify_master_failure=true

    # 当Maxscale连接不上master时,开启其他slave再次验证master是否故障。这样的好处是:防止网络抖动误切换(脑裂),造成数据不一致,其实现原理为:投票机制,当Maxscale无法连接MySQL主库,会试图从其他slave机器上去连接MySQL主库,只有双方都连接失败,才认定MySQL主库宕机。假如有一方可以连接MySQL主库,都不会切。

    类似MHA的masterha_secondary_check命令二次检查,默认开启,无需关闭。

    master_failure_timeout=10

    # 这个参数依赖于verify_master_failure,当开启后,从库在默认10秒内无法连接master,认定主库down掉。通常默认值即可。

    ② 服务模板

    这里我们要定义一个服务,路由选择读写分离模块。你可以分离一部分select读取操作到slave从库上。它是基于statement的,解析SQL语句。在这里前端程序不需要修改代码,通过MaxScale对SQL语句解析,把读写请求自动路由到后端数据库节点上,从而实现读写分离。开源Percona ProxySQL中间件也是基于statement方式实现读写分离。

    [Read-Write-Service]

    master_accept_reads=true

    # 如果你担心数据有延迟,担心数据准确性问题,可以设置在主库上查询。默认读是不被路由到master,设置为true允许master用于读取。

    max_slave_connections=2

    # 允许两个slave进行读取

    max_slave_replication_lag=1

    # 定义超过延迟1秒,把请求转发给master

    causal_reads=local

    # 由于Maxscale通过参数monitor_interval=2000,每隔2秒探测一次,可能存在主从延迟检测不到的情况。

    例如主库上写入了一条数据,从库还没来得写入该记录。那么可以通过设置causal_reads=local,此时客户端在从库上查询会hang住,直至等待causal_reads_timeout=10,默认10秒,超时后请求会强制转发给master。

    # 全局配置段,配置MaxScale服务器的运行参数

    [maxscale]
    threads=auto

    # 以下的所有段落为MaxScale对外提供服务所需要的参数
    # 注意“节”名称不能包含空格,如有需要可以使用-/_代替。
    # 各个“节”有不同的作用,MaxScale根据type参数来判断各个“节”是干什么的,
    # 而不是根据“节”的名称来判断的。
    # 这里这个配置文件一共有四个type: server(后端服务器)
    # monitor(监控), service(服务,可以理解为路由)
    # listener(监听器,由于对外提供服务)
    [server1] # 指定服务器一的配置
    type=server
    address=10.0.0.101 # 指定服务器地址
    port=63132 # 指定服务器端口
    # socket=/var/lib/mysql/mysql.sock # 指定服务器的unix socket路径
    # 如果 MaxScale 和 MariaDB 在同一台主机上,可以使用这种方法连接
    # 不过需要注意,socket 用法与 address/port 是冲突的,只能选其一。
    # 同时需要注意 MariaDB 的权限配置。
    protocol=MariaDBBackend # 指定连接使用的协议。
    # 这里使用的是 MariaDBBackend 是 MariaDB 开发的特殊协议,
    # 可以加快 MaxScale 访问 MariaDB 的访问速度。

    [server2]
    type=server
    address=10.0.0.102
    port=3306
    protocol=MariaDBBackend

    [server3]
    type=server
    address=10.0.0.103
    port=3306
    protocol=MariaDBBackend

    [MariaDB-Monitor]
    type=monitor
    module=mariadbmon # 指定启用模块 mariadbmon
    # 此模块为监控模块,针对 MariaDB 服务器使用的监控模块,基础功能是用于监控服务器的健康状态的。
    # 同时此模块能判断主从,当主服务器发生故障时还能完成自动化故障转移的操作,当然这些功能需要
    # 手动开启,这些会在后面说明的。
    # 这些模块都是以 so 形式保存在 /usr/lib64/maxscale/ 目录中的。
    # 注: 主服务器一定要确保关闭 read_only,否则将判定主服务器是一个不可用的服务器,这将导致整个集群不可用。
    servers=server1,server2,server3 # 指定需要对哪些服务器进行监控
    # 这里的 server1,server2,server3 与上面的后端服务器“节”名称对应。
    user=maxscale # 指定监控使用的用户
    password=111E15EBF48383FE639F9E134A956826 # 指定密码
    # 这里就是经过加密的密码,密码为123456。
    monitor_interval=2000ms # 指定监控间隔事件这里是2秒

    [Read-Write-Service]
    type=service
    router=readwritesplit # 指定启用模块,readwritesplit
    # 注意虽然前面写的是router,但是后面跟的还是模块名称。
    # 此模块为路由模块,用于读写分离使用,它同通过监控模块获取服务器主从信息,自动完成读写分离。
    # 它会将所有读取类操作都优先分发给从服务器使用,而写入类操作全部发送给主服务器,
    # 修改变量类的操作将发送到所有服务器。
    servers=server1,server2,server3
    user=maxscale
    # 注意,这里填写的用户是用来进行用户认证的。
    password=111E15EBF48383FE639F9E134A956826

    [Read-Write-Listener]
    type=listener
    service=Read-Write-Service
    # 这里指定的服务,需要与上面对应。
    protocol=MariaDBClient
    # 指定协议 MariaDBClient 也就是 MySQL 协议。
    port=3306
    # 指定端口
    # 可以使用 UNIX 套接字,而不是端口监听。
    # socket=default
    # 默认 UNIX sock 路径为 /var/run/maxscale/maxscale.sock
    # 注意 socket 和 port 是冲突的。

    MaxScale 自动化故障转移

    GTID(全局事务ID),由域ID(默认值为0,可以通过gtid_domain_id变量来进行修改)、服务器ID和事务事务ID组成的的全局唯一标识符,例如:0-100-22。

    设立全局事务ID的目的是为了保证数据的高可用性,能非常轻松的实现中断恢复,而不用担心数据会有遗漏的问题,因为每一个事务都会标有一个全局唯一的GTID(记录在二进制日志文件中),只需要从对应的GTID开始恢复即可。

    注:MariaDB默认开启了GTID功能,当有事务提交时,将会生成全局唯一的GTID。

    因为 MaxScale 会通过监控模块完成进行故障转移操作,所以需要给予'maxscale_monitor'@'10.0.0.%' SUPER 和 RELOAD 权限。

    GRANT SUPER, RELOAD ON *.* TO 'maxscale_monitor'@'172.16.1.%';
    

    从服务器需要开启二进制日志。

    当主服务器挂了时,将会挑选一台从服务器提升主服务器使用,此时就需要使用二进制日志功能了。

    从服务器可以选择开启read_only,MaxScale 会自动检测该值,当需要将从服务器提升未主服务器时,会自动关闭该属性。

    三台数据库修改服务配置文件:

    [root@nfs ~]# cat > /etc/my.cnf.d/mysql-clients.cnf <<EOF
    
    ……
    log-bin=bin-log
    log-bin-index=bin-log.index
    relay-log=relay-log
    # 可选配置,MariaDB以从服务器运行时,将会开启。
    relay-log-index=relay-log.index
    # 上同
    server-id=100 #注意不要使用相同的服务器ID号。
    ……
    

    编辑MaxScale的配置文件

    # file: /etc/maxscale.cnf
    
    ……
    [MariaDB-Monitor]
    type=monitor
    module=mariadbmon
    servers=server1,server2,server3
    user=maxscale_mon
    password=111E15EBF48383FE639F9E134A956826
    monitor_interval=2000ms
    # 指定复制用户的用户名和密码
    # 如果未指定,将使用user和password
    replication_user=maxscale_mon
    replication_password=111E15EBF48383FE639F9E134A956826
    # 指定开启自动故障转移
    auto_failover=true
    # 指定开启自动加入集群(将以从服务器模式加入)
    auto_rejoin=true
    ……
    [Read-Write-Service]
    type=service
    router=readwritesplit
    servers=server1,server2,server3
    user=maxscale
    password=111E15EBF48383FE639F9E134A956826
    # 当主服务器挂了时,客户端的写入操作将会返回错误,服务器以只读模式运行。
    # 如果没有设置此值,那么当客户端执行写入操作时,MaxScale将会直接断开连接。
    master_failure_mode=error_on_write
    # 当此选项启用时,并且master_failure_mode 设置为 fail_on_write|error_on_write 时,
    # 将会取消只读模式,客户端的写入请求将会被重新处理。
    master_reconnection=true
    ……
    

    配置从服务器使用GTID,两台从服务器使用相同的命令即可:

    # 停止从服务器
    stop slave;
    # 重置从服务器
    reset slave;
    # 配置指定主服务器,注意,这里指定主服务器使用GTID MASTER_USE_GTID=current_pos
    # MASTER_USE_GTID一个有三个可选项 slave_pos、current_pos、no
    # slave_pos 选项将使用 gtid_slave_pos 变量指定的值
    # current_pos 选项将使用 gtid_current_pos 变量指定的值
    # 注意,gtid_current_pos、gtid_binlog_pos值是只读的
    # gtid_current_pos 值是 gtid_binlog_pos 和 gtid_slave_pos 两个变量的并集
    # gtid_binlog_pos 当服务器有事务提交时将设置该变量
    CHANGE MASTER TO MASTER_HOST='172.16.1.51', MASTER_PORT=63132, MASTER_USER='maxscale_monitor', MASTER_PASSWORD='123456', MASTER_USE_GTID=current_pos;
    # 启动从服务器
    start slave;
    
    # 注意,如果再从服务器上面提交了事务,那么它会产生 gtid_binlog_pos,这将有可能
    # 导致 gtid_current_pos,需要使用以下命令来重置它:
    # 注意,这样同时会重置二进制日志文件,需要谨慎使用。
    # 重启 maxscale 服务器:
    reset master;
    

    MaxScale 远程管理使用

    MaxScale 开发了新的管理接口(reset API),使用了HTTP协议,用户认证也将基于 HTTP 协议完成。如果需要基于 MaxScale 做开发也就会变得更加方便,同时新的管理工具 maxctrl 也使用了该接口,老版的管理工具 maxadmin 和 API 由于在安全方面存在问题即将被废弃。
    由于使用HTTP协议,所以可以MaxScale也支持 HTTPS,同时为了增强安全性,也开启了证书的双向认证。也就是说当客户端连接服务器时需要提供客户端的公钥用于认证客户端是否有效,客户端也将验证服务器证书,当然前提是这些证书都必须由同一CA颁发的,否者将无法完成认证。

    默认 MaxScale 就开启了reset API,现在创建一下证书文件,然后配置 MaxScale 使用证书即可。

    # 首先是创建CA服务的证书文件
    mkdir -p /etc/pki/CA/private
    mkdir /etc/pki/CA/newcerts
    cd /etc/pki/CA
    openssl genrsa -out private/cakey.pem 2048
    openssl req -new -x509 -key private/cakey.pem -out cacert.pem # 这里的证书创建过程就省略不写了。
    # 不过需要注意的是,必须要保证后面服务器证书申请的开头部分必须与证书开头相同,否则无法通过CA签发证书。
    # 同时需要注意,颁发的服务器名称(commonName)需要与主机名称(FQDN)对应,必须要能解析到。
    touch index.txt
    echo "01" > serial
    # 创建 MaxScale 服务器证书
    cd /var/lib/maxscale/
    openssl genrsa -out maxscale.key 2048
    openssl req -new -key maxscale.key -out maxscale.csr
    openssl ca -in maxscale.csr -out maxscale.crt -days 365
    # 创建客户端证书
    mkdir ~/.cert/
    cd ~/.cert/
    openssl genrsa -out client.key 2048
    openssl req -new -key client.key -out client.csr
    openssl ca -in client.csr -out client.crt -days 365
    配置 MaxScale 使用证书:

    [maxscale]
    threads=auto
    admin_host=0.0.0.0
    # 指定监听 0.0.0.0, 默认监听 127.0.0.1
    admin_port=8989
    # 指定监听端口,默认就是 8989
    admin_ssl_key=/var/lib/maxscale/maxscale.key
    # 指定服务器密钥
    admin_ssl_cert=/var/lib/maxscale/maxscale.crt
    # 指定服务器公钥
    admin_ssl_ca_cert=/etc/pki/CA/cacert.pem
    # 指定CA证书
    # 注意,只有以上三个参数都配置了,HTTPS 才会生效,并且将强制使用HTTPS
    ……
    这里偷个懒,在 hosts 文件中编写主机名,最好是在DNS中配置,方便管理。

    # file: /etc/hosts

    ……
    10.0.0.101 server1 # 注意,这里我使用的主机名为 server1
    # 如果使用不同的主机名需要手动修改。
    然后再重新测试软件

    systemctl restart maxscale # 重启服务器,使配置生效
    # 测试是否可用
    maxctrl -s --tls-key /root/.cert/client.key --tls-cert /root/.cert/client.crt --tls-ca-cert /etc/pki/CA/cacert.pem -h server1:8989 list servers
    # 注意,一定要使用主机名,而不是IP地址,client会检测证书是否与主机名对应,这也就是为什么需要配置 hosts 的原因。

    maxctrl SSL 连接

    maxctrl 简易用法
    maxctrl 使用方法:

    maxctrl [OPTIONS] [COMMAND]
    注:maxctrl 如果不指定 COMMAND 将会进入交互式,在交互式中可以直接输入
    COMMAND 即可,不过由于未知原因,当启用 HTTPS 时,将无法使用交互式执行命令。
    这些应该会在后续的更新中修复。
    
    OPTIONS:
    -u --user 指定用户
    -p --password 指定用户密码
    -h --hosts 指定主机
    -t --timeout 指定超时时间 [单位:毫秒]
    -q --quiet 静默输出,将不输出任何参数。
    --tsv 使用 TAB 作为分隔符
    -s --secure 指定启用 HTTPS 请求 [Bool 默认: false]
    --tls-key 指定连接使用的私钥
    --tls-passphrase 指定连接使用的私钥密码
    --tls-cert 指定连接使用的公钥
    --tls-ca-cert 指定CA公钥
    -n --tls-verify-server-cert 检测服务器证书是否有效 [Bool 默认: true]
    --version 显示软件版本包
    --help 查询帮助信息
    
    COMMAND:
    # 以表格格式显示基础信息
    list servers # 显示所有后端服务器
    list services # 显示所有服务,例如读写分离服务等
    list monitors # 显示所有监控信息
    list listeners # 显示监听信息
    list threads # 显示线程
    list modules # 显示模块
    list sessions # 显示所有用户进程
    list commands # 显示所有模块的可用指令
    # 在以上的基础上显示更加详细的服务信息
    show servers # 显示所有后端服务器的详细信息
    show server # 显示后端服务器的详细信息
    show service # 显示服务的详细信息
    show services # 显示所有服务的详细信息
    show monitor # 显示监控的详细信息
    show monitors # 显示所有监控的详细信息
    show session # 显示用户进程信息
    show sessions # 显示所有用户进程信息
    show module # 显示模块的详细信息
    show modules # 显示所有模块的详细信息
    # 对 MaxScale 做出修改类的命令,注意如果做出了修改,那么将会永久成效,默认配置文件 /etc/maxscale.cnf 中的冲突部分将不再生效。
    # 实际上做出了修改之后,maxscale 的配置会存放至 /var/lib/maxscale/maxscale.cnf.d/ 目录下。
    clear server # 清除服务的指定属性,例如 Maintenance(维护模式)
    drain server # 等待指定服务的所有链接线程结束,会将服务器标注为维护模式(Maintenance),新的连接将不会发送给该服务器。
    destroy server # 销毁指定的服务器,指定服务器必须断开service和monitor连接
    link service # 指定后端服务器连接 服务。
    link monitor # 指定后端服务器连接 监控
    unlink service # 指定断开服务与后端服务器的链接
    unlink monitor # 指定断开监控与后端服务器的链接
    create user # 创建一个用户,默认用户具有只读权限,如果想要创建为管理员用户可以添加参数 --type=admin
    destroy user # 删除一个用户
    

    注:这里只是其中的一些命令,详细可以去查看官方文档。

    SQL常用命令

    # 导入数据库
    mysql -uroot -p123  < /tmp/mysql-all.sql
    
    # 导出数据库
    mysqldump -uroot -p123 -A > /tmp/mysql-all.sql
    
    # 查看MYSQL数据库中所有用户
    SELECT DISTINCT CONCAT('User: ''',user,'''@''',host,''';') AS query FROM mysql.user;
    
    # 查看数据库中具体某个用户的权限
    show grants for 'zabbix'@'%';
    select * from mysql.user where user='zabbix' G
    
    # 查看user表结构 需要具体的项可结合表结构来查询
    desc mysql.user;
    
    # 创建数据库
    create database zabbix character set utf8 collate utf8_bin;
    grant all privileges on zabbix.* to zabbix@localhost identified by '123456';
    
    # 查看所有数据库
    show databases;
    
    # 授权所有权限 grant all
    # 授权所有库所有表 *.*
    # 将授权赋予给哪个用户,这个用户只能通过哪个网段过来(%所有) 'lzy'@'%'
    # 授权该用户登录的密码 identified by
    grant all on *.* to 'root'@'%' identified by '123';
    
    删除用户
    Delete FROM mysql.user Where User='zabbix' and Host='localhost';
    
    # 刷新
    flush privileges;
    
    # 重新记录日志,将停止记录当前日志,开始将日志写入下一个日志。
    FLUSH LOGS;
    # 启动从服务器
    START SLAVE;
    # 停止从服务器
    STOP SLAVE;
    # 重置从服务器配置
    RESET SLAVE;
    # 重置主服务器配置
    RESET MASTER;
    # 显示二进制日志文件状态
    SHOW BINARY LOGS;
    # 显示主服务器状态
    SHOW MASTER STATUS;
    
  • 相关阅读:
    Linux 文件特殊权限
    Linux ACL权限
    Linux 用户管理命令
    Asm.js: Javascript的编译目标
    《Zero to One》的一些读书笔记
    Tomcat架构(四)
    Tomcat架构(三)
    Tomcat架构(二)
    Tomcat 架构 (一)
    MATERIAL DESIGN学习笔记
  • 原文地址:https://www.cnblogs.com/backups/p/maridb_maxscale.html
Copyright © 2020-2023  润新知