近期项目组在使用mycat去做mysql的读写分离时有遇到一些问题,如在要求使用useCursorFetch=true时,后端路由转发可能会不正常,为此寻找替代mycat的中间件。项目只需求库级别(不涉及到分区表)的读写分离和读的负载均衡,maxscale较为符合,记录下在Centos7下安装maxscale以及简单的读写分离测试

一、环境准备

数据库是一主两从的机构(mysql的主从搭建不在此说明),maxscale安装在主库所在服务器上(也可以不与数据库安装在同一服务器上)

hostname

ip

status

mysql-master

192.168.2.18

主库 提供写服务

mysql-slave1

192.168.2.19

从库 提供读服务

mysql-slave2

192.168.2.20

从库 提供读服务

二、下载安装

Maxscale是由MariaDB官方提供的中间件,并负责升级和维护,可在官网中进行下载,另外可以查看官方提供的详细文档,本例中所有的安装方式都是选用maxscale-2.4版本。

1、以yum的方式安装

在网络条件运行的情况下,我会优先选用yum的方式进行安装部署,对此官网也提供了详细的说明文档:MariaDB Package Repository Setup and Usage,这里做简单的记录。

  • 下载yum源文件
curl -LsS https://downloads.mariadb.com/MariaDB/mariadb_repo_setup |
    sudo bash -s -- --mariadb-maxscale-version="2.4"  --os-type=rhel --os-version=7

正常完成会有如下提示:

mariadb参数调整 mariadb maxscale_mysql

  • 确认下源文件中有所需的maxscale
    yum search maxscale
  • 下载安装
    yum install maxscale
  • 启动
    systemctl start maxscale

2、以rpm的方式安装

  • 下载安装rpm包
    官网上下载自己所需版本的安装包。
  • 安装
    rpm -ivh maxscale-2.4.13-1.rhel.7.x86_64.rpm

[NOTE]
我的环境是直接安装成功了,有些环境可能会报错提示需要安装一些依赖,这里也说明一下:yum install libcurl libaio OpenSSL gnutls

  • 启动
    CentoOS7下使用rpm方式安装完成后会自己创建对应的maxscale.service文件,以及配置文件默认在/etc/maxscale.cnf,直接使用systemctl方式启动即可:
    systemctl start maxscale

3、以编译的方式安装

4、直接下载文件部署使用

三、参数配置

  • 以yum或rpm方式安装的maxscale,默认的参数文件是/etc/maxscale.cnf,也可以在启动的时候使用-f参数指定参数文件,如maxscale -f /u01/maxscale.cnf。每个版本的参数文件会所有不同,官网提供了详细的参数文件说明,本例记录了一些项目所需的参数说明。
  • 先看一份配置好的参数文件
# 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]
threads=auto
# log
syslog=0
# syslog=<0|1> 是否将log记录到/var/log/messages中       
maxlog=1
# maxlog=<0|1> 将日志记录到file,默认在/var/log/maxscale/maxscale.log
log_info=1
# <0|1> 设置日志的级别为info
# logdir=/tmp
# 日志的存储位置,不设置的话默认在/var/log/maxscale/,需要对目录有读写权限

# datadir=
# 数据文件存储目录,默认在/var/lib/maxscale     
# piddir=
# pid文件存储目录,默认在/var/run/maxscale     

# Server definitions
#
# Set the address of the server to the network
# address of a MariaDB server.
#

[server1]
type=server
address=192.168.2.18
port=3306
protocol=MariaDBBackend

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

[server3]
type=server
address=192.168.2.20
port=3306
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=scalemon
password=123456
monitor_interval=2000

# Service definitions
#
# Service Definition for a read-only service and
# a read/write splitting service.
#

# ReadConnRoute documentation:
# https://mariadb.com/kb/en/mariadb-maxscale-24-readconnroute/

# [Read-Only-Service]
# type=service
# router=readconnroute
# servers=server1
# user=myuser
# password=mypwd
# router_options=slave

# ReadWriteSplit documentation:
# https://mariadb.com/kb/en/mariadb-maxscale-24-readwritesplit/

[Read-Write-Service]
type=service
router=readwritesplit
servers=server1,server2,server3
user=maxscale
password=123456
max_slave_connections=100%

# connection_timeout=300
# max_connections=100

max_slave_replication_lag=60
# 允许主从最大延迟(s),超过此数值从库不接受读请求    

# master_reconnection=1
# master_failure_mode=error_on_write

# Listener definitions for the services
#
# These listeners represent the ports the
# services will listen on.
#

# [Read-Only-Listener]
# type=listener
# service=Read-Only-Service
# protocol=MariaDBClient
# port=4008

[Read-Write-Listener]
type=listener
service=Read-Write-Service
protocol=MariaDBClient
port=4006
  • 参数文件中主要是5个模块,Global parameters、Server definitions、Monitor for the servers、Service definitions和Listener definitions for the services。
  • Global parameter是全局参数,上述文件中主要对线程数和日志做了设置
  • threads=auto表示跟CPU核数一样也可以自定义其他数值;
  • 对于log日志,只需要记录在专门的日志文件即可,无需在syslog再记录一份,日志级别需要查看每条查询的路由情况可以把info级别开启,后续需要注意日志文件逐渐变大,可做转储;
  • 其余参数不进行配置使用默认的即可。
  • Server definitions配置了后端数据库,参考上述文件即可,其中protocol目前只有MariaDBBackend协议。
  • Monitor for the servers是配置监控后端数据库的相关参数,其中有几种模式,这里采用的是mariadbmon
  • servers的值对应上一个模块中后端数据库,用逗号隔开;
  • monitor_interval设置的是监控频率,单位是ms,默认是2000ms;
  • user和password是监控数据库时所用到的数据库用户和密码,此用户需要在数据库上创建并赋权,需要replication和client权限
    grant replication client on *.* to to scalemon@'%' identified by '123456';
  • Service definitions是配置我们所用的服务策略,如readconnroute和readwritesplit等,项目主要是需要读写分离,即readwritesplit。
  • router设置成readwritesplit;
  • max_slave_connections设置成100%,表示读负载到所有的slave数据库
  • max_slave_replication_lag设置的是从库最大延迟,单位是秒,即当从库的延迟大于所设置的值时,读请求不再路由到此从库上
  • user和password是路由账号,maxscale使用该账号将不同的请求分发到不同的节点上。当客户端连接到maxscale这个节点上时,maxscale节点会使用该账号去查后端数据库,检查客户端登陆的用户是否有权限或密码是否正确等等;
    grant select on mysql.* to maxscale@'%' identified by '123456';grant show databases on *.* to maxscale@'%' identified by '123456';
  • master_reconnection和master_failure_mode是设置主库宕机下的配置
    master_failure_mode有三个值,fail_instantly、fail_on_write和error_on_write,默认是fail_instantly即当主库宕机时,立即关闭连接并不再接受新连接;fail_on_write和error_on_write分别代表是主库宕机的情况下,当有写请求连接来时,分别断开连接和报错,即主库宕机时只接受只读连接;如果主库恢复了,只读连接在不断开的情况下变成读写连接的话,就需要master_reconnection设置成1,即enable。
  • Listener definitions for the services用于配置上述服务策略的监听
  • service设置成上述服务策略中的对应名称
  • protocol目前只支持MariaDBClient
  • port监听的端口,读写分离默认的是4006,只读默认的是4008。

四、命令说明

1、maxscale

  • 用于启动maxscale,可以添加参数,maxscale --help
  • 以yum和rpm方式安装,有些默认的参数如下:
config file       : /etc/maxscale.cnf
configdir         : /etc
logdir            : /var/log/maxscale
cachedir          : /var/cache/maxscale
libdir            : /usr/lib64/maxscale
datadir           : /var/lib/maxscale
execdir           : /usr/bin
language          : /var/lib/maxscale
piddir            : /var/run/maxscale
persistdir        : /var/lib/maxscale/maxscale.cnf.d
module configdir  : /etc/maxscale.modules.d
connector plugins : /usr/lib64/mysql/plugin

2、maxctrl

  • 在老的版本中是maxadmin,2.4及之后的版本开始统一使用maxctrl命令来操作maxscale,先看下基本格式maxctrl --help

查看具体命令的使用方法,如查看list命令的使用方法:maxctrl help list

  • 查看后端数据库
    maxctrl list servers
  • 查看maxscale的服务策略
    maxctrl list services

[NOTE]
更多的命令可以自行结合help命令去尝试。

五、简单的测试

1、读写分离测试

  • 创建一个用于测试的数据库用户:grant all on *.* to scott@'%' identified by 'tiger';
  • 通过maxscale访问数据库:mysql -uscott -ptiger -h192.168.2.18 -P4006
  • 验证读写分离

可以看到读的请求发送到了从库上,写的请求发送到的主库上,如果log日志开启了info级别,在日志中也可以清楚看到路由情况。

2、只读从库负载均衡测试

  • 开启三个窗口执行:mysql -uscott -ptiger -h192.168.2.18 -P4006 -BNe "select @@hostname;select sleep(100);"

可以看到三次读请求分别路由到了slave1、slave2、slave1上,实现了负载均衡

[NOTE]
对于负载均衡还可以设置权重,具体的设置方法可以参考官方文档进程参数调整。

3、从库延迟配置测试

  • 开启从库延迟限制,即设置max_slave_replication_lag=60
  • 在slave1上执行:flush table with read lock;
  • 在master上创建一个test数据库,并创建一张t1表,插入一条数据
  • 通过maxscale连接数据库查询:mysql -uscott -ptiger -h192.168.2.18 -P4006 -BNe "select @@hostname;"

一分钟后再次执行上述语句:

mariadb参数调整 mariadb maxscale_mysql_02

可以看到slave1上的延迟超过60s,读请求不再发送到slave1,而且路由到了没有延迟的slave2上。在slave1上解除表锁unlock tables;后slave1重新接受读请求。

4、主库从库分别宕机测试

  • 单独关闭slave1,模拟一台从库宕机
  • 继续关闭slave2,模拟两台从库都宕机

读查询路由到了主库中,老的版本可能还需要配置detect_stale_master=true,2.4版本已经不再需要配置此参数。

  • 开启两台从库,然后关闭主库
  • 直接关闭主库,即默认master_failure_mode=fail_instantly
  • 设置master_reconnection=1,master_failure_mode=error_on_wirte后关闭主库,然后再开启主库

可以看到通过maxscale还是可以连接数据库,并且可以执行只读查询,当要进行写操作时,有报错提示,说明此时数据库在只读模式下,然后重启主库之后,直接恢复,无需重新开个连接。

  • 设置master_reconnection=1,master_failure_mode=fali_on_wirte后关闭主库,然后再开启主库

一样可以通过maxscal连接数据库,并且可以执行只读查询,当要进行写操作时,是fail的报错,然后重启主库之后,再进行写操作时,会自己重连主库,也是无需重新卡个新的连接。

六、其他

  • maxscale配置简单,能实现读写分离和读的负载均衡,但是本身没有高可用的功能,不能提供数据库的高可用,本身节点也要配合类似keepalived才能实现高可用。
  • 测试中发现只要开启事务,就会路由到主库上,据了解java中对事务本身可以定义只读事务、读写事务等,当然理想情况下希望只读事务也可以路由到从库中执行,这一点还需要再做测试