主从复制
主从复制集群中,主节点启用二进制日志,从节点启动中继日志。主节点接收到任何一个连接线程发出的写请求操作后,对数据文件进行修改,同时将该操作写入二进制文件。从节点将启动一个连接线程,此时从节点为客户端,主节点为服务器,这个连接线程将请求主节点监控二进制日志是否有新的事件被填入,若有则请求主节点将事件发送给从节点。从节点会启动I/O线程和SQL线程,主节点会为每一个连接过来的I/O线程启动dump线程,由dump线程负责将事件发送给I/O线程,I/O线程接收到事件后将其保存到本地的中继日志中。I/O线程负责加载事件到中继日志中,SQL线程负责从中继日志加载事件并重放事件。主从复制集群中,主节点可以接收客户端的读请求和写请求,从节点只能接收客户端的读请求。
下面将简单介绍一主一从模型的实现:
1 主节点
在配置文件/etc/my.cnf.d/server.cnf中做如下修改:
server_id=#
log_bin=log-bin
server_id=1定义当前节点的ID,在主从复制集群中,每个节点的ID唯一
log_bin=log-bin启用二进制日志,使用相对路径,即相对于数据库文件存放目录的路径
mysql> GRANT REPLICATION SLAVE,REPLICATION CLIENT ON *.* TO 'USERNAME'@'HOST' IDENTIFIED BY 'YOUR_PASSWORD';
mysql> FLUSH PRIVILEGES;
创建并授权具有复制二进制日志权限的账号
2 从节点
在配置文件/etc/my.cnf.d/server.cnf中做如下修改:
server_id=#
relay_log=relay-log
read_only=ON
relay_log=relay-log启用中继日志
mysql> CHANGE MASTER TO MASTER_HOST='HOST',MASTER_USER='USERNAME',MASTER_PASSWORD='YOUR_PASSWORD',MASTER_LOG_FILE='BINLOG',MASTER_LOG_POS=#;
MASTER_HOST定义主节点
MASTER_USER定义主从复制账户
MASTER_PASSWORD定义主从复制账户的密码
MASTER_LOG_FILE定义主节点二进制日志文件
MASTER_LOG_POS定义主节点二进制日志文件的位置
mysql> START SLAVE [IO_THREAD|SQL_THREAD];
从节点启动I/O线程和SQL线程
双主模型的配置与一主一从模型类似,需注意以下几点:
1、server_id必须要使用不同值;
2、均启用binlog和relay log;
服务启动后执行如下两步:
1、都授权有复制权限的用户账号;
2、各把对方指定为主节点;
半同步复制
异步复制:当写操作到达主节点时,主节点根据该操作对数据文件进行修改,并将该操作写入二进制文件,然后就返回响应报文给客户端。从节点此时可能正在重放主节点之前的操作,还需一段时间才会重放刚刚主节点所执行的操作,即主节点不等待从节点完成操作;
同步复制:当写操作到达主节点时,主节点根据该操作对数据文件进行修改,并将该操作写入二进制文件,从节点此时可能正在重放主节点之前的操作,还需一段时间才会执行刚刚主节点所执行的操作,主节点将一直等待,直到从节重放刚刚主节点所执行的操作,对本地的数据文件做出相应修改,然后主节点才返回响应报文给客户端。
在没有特别指明时,mysql的复制模式都是异步复制,即一主一从、一主多从、双主模型中都是异步复制,半同步复制模型中,除了主节点与同步从节点之间是同步复制外,主节点与其他从节点之间都是异步复制。
实现半同步复制需进行如下配置:
1 主节点
MariaDB [mydb]>INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
MariaDB [mydb]> SHOW GLOBAL VARIABLES LIKE 'rpl_semi%';
+------------------------------------+-------+
| Variable_name | Value |
+------------------------------------+-------+
| rpl_semi_sync_master_enabled | OFF |
| rpl_semi_sync_master_timeout | 10000 |
| rpl_semi_sync_master_trace_level | 32 |
| rpl_semi_sync_master_wait_no_slave | ON |
+------------------------------------+-------+
MariaDB [mydb]> SET GLOBAL rpl_semi_sync_master_enabled=ON;
mariadb的插件目录为/usr/lib64/mysql/plugins/,其中很多插件并未被安装激活,要实现半同步复制需安装rpl_semi_sync_master插件,其中semisync_master.so是rpl_semi_sync_master插件的共享模块文件名。
SET GLOBAL rpl_semi_sync_master_enabled=ON启动主节点半同步复制
2 从节点
MariaDB [mydb]>INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_slave.so';
MariaDB [mydb]> SHOW GLOBAL VARIABLES LIKE 'rpl_semi%';
+------------------------------------+-------+
| Variable_name | Value |
+------------------------------------+-------+
| rpl_semi_sync_master_enabled | OFF |
| rpl_semi_sync_master_timeout | 10000 |
| rpl_semi_sync_master_trace_level | 32 |
| rpl_semi_sync_master_wait_no_slave | ON |
+------------------------------------+-------+
MariaDB [mydb]> SET GLOBAL rpl_semi_sync_slave_enabled=ON;
SET GLOBAL rpl_semi_sync_slave_enabled=ON启动从节点半同步复制
MariaDB [mydb]> STOP SLAVE IO_THREAD;
MariaDB [mydb]> START SLAVE IO_THREAD;
重启从节点的复制线程
MariaDB [mydb]> SELECT @@global.rpl_semi_sync_master_clients;
rpl_semi_sync_master_clients 变量值为半同步复制客户端即同步从节点个数,可以通过查看该变量的值检验半同步复制配置是否成功
读写分离
对mysql的主从复制集群,主节点可以接收读请求和写请求,从节点只能接收读请求,为了降低主节点的负载,可以使用ProxySQL实现读写分离。
一 ProxySQL简介及安装
ProxySQL is a high performance, high availability, protocol aware proxy for MySQL and forks (like Percona Server and MariaDB).
其最新版的软件可从http://www.proxysql.com/下载安装。
二 原理及配置
1 ProxySQL实现读写分离的原理
在ProxySQL所在主机即代理服务器上需监听127.0.0.1的6082端口和本机所有地址的3306端口:
6082端口负责接收本机的管理请求,即用户可以通过在代理服务器上连接本机的6082端口对代理服务器进行管理和配置。3306端口负责接收客户端连接数据库的请求:
当客户端执行
mysql -udbadmin -pdbpass -h172.18.0.69
即客户端以dbadmin的用户名,dbpass的密码连接代理服务器ProxySQL(172.18.0.69)时,请求将到达172.18.0.69即代理服务器ProxySQL的3306端口,然后代理服务器ProxySQL将写请求调度至后端mysql服务器主节点,将读请求调度至后端mysql服务器主节点。对后端mysql服务器来说,客户端是172.18.0.69,请求报文源地址是172.18.0.69;对客户端来说,mysql服务器是172.18.0.69,响应报文源地址是172.18.0.69。
2 配置
ProxySQL的配置文件为 /etc/ProxySQL.conf,实现读写需在配置文件中做如下配置:
datadir="/var/lib/proxysql"
定义数据目录
admin_variables=
{
admin_credentials="admin:admin"
mysql_ifaces="127.0.0.1:6032;/tmp/proxysql_admin.sock"
}
ProxySQL内建的管理接口,此类接口最好不要开放给其他主机访问,所以最好只监听127.0.0.1的6032端口,同时科技监听本机的套接字文件,但套接字文件只能监听本机的请求,即本机为客户端时才可用该套接字文件建立连接,由于管理接口一般仅在本机访问,所以此处监听套接字文件是有意义的。
mysql_variables=
{
threads=4
max_connections=2048
default_query_delay=0
default_query_timeout=36000000
have_compress=true
poll_timeout=2000
interfaces="0.0.0.0:3306;/tmp/mysql.sock"
default_schema="information_schema"
stacksize=1048576
server_version="5.5.30"
connect_timeout_server=3000
monitor_history=600000
monitor_connect_interval=60000
monitor_ping_interval=10000
monitor_read_only_interval=1500
monitor_read_only_timeout=500
ping_interval_server=120000
ping_timeout_server=500
commands_stats=true
sessions_sort=true
connect_retries_on_failure=10
}
ProxySQL的管理变量定义段定义了线程数、最大并发连接数、查询超时时长等变量,可根据具体生产环境要求进行设置。其中,需特别强调的是
interfaces=”0.0.0.0:3306;/tmp/mysql.sock”这一项,interfaces定义了ProxySQL作为代理服务器监听的端口,一般是后端mysql服务器的默认监听端口,即3306,以便客户端连接,也可以监听在其他端口,但此时客户端连接需指明端口,一般不需监听套接字文件,因为套接字文件只能监听本机的请求,即本机为客户端时才可用该套接字文件建立连接,由于数据库服务一般不在本机访问,所以此处监听套接字文件是无意义的。
mysql_servers =
(
{
address = "172.18.0.67" # no default, required . If port is 0 , address is interpred as a Unix Socket Domain
port = 3306 # no default, required . If port is 0 , address is interpred as a Unix Socket Domain
hostgroup = 0 # no default, required
status = "ONLINE" # default: ONLINE
weight = 1 # default: 1
compression = 0 # default: 0
},
{
address = "172.18.0.68"
port = 3306
hostgroup = 1
status = "ONLINE" # default: ONLINE
weight = 1 # default: 1
compression = 0 # default: 0
}
)
定义后端mysql服务器,每个{}对应一个后端服务器,每个{}间用逗号隔开,最后一个{}后不加逗号。
hostgroup 定义mysql服务器所属组
weight 定义mysql服务器权重
本实验中定义172.18.0.67属于0组,172.18.0.68属于1组。
mysql_users:
(
{
username = "dbadmin"
password = "dbpass"
default_hostgroup = 0
max_connections=1000
default_schema="mydb"
active = 1
}
)
default_hostgroup 定义请求调度的默认组
max_connections 定义最大并发连接数
default_schema 定义默认的数据库
该段主要用于定义客户端与服务器建立连接时使用的账号,同时也是代理服务器连接后端服务器时使用的账号,该账号可以使用以下代码需事先在后端服务器创建账号并授权:
GRANT ALL ON*.* TO IDENTIFIED BY'dbpass';
FLUSH PRIVILEGES;
#defines MySQL Query Rules
mysql_query_rules:
(
{
rule id=1
active=1
match_pattern="SELECT .* FOR UPDATES"
destination_hosstgroup=0
apply=1
}
{
rule id=1
active=1
match_pattern="^SELECT "
destination_hosstgroup=0
apply=1
}
)
查询规则:SELECT语句并不完全属于读请求,将涉及更改的SELECT语句发送给0组即主节点所在组,其他类型的SELECT语句发送给1组即从节点所在组。
mysql_replication_hostgroups=
(
{
writer_hostgroup=0
reader_hostgroup=1
}
)
定义主从复制集群,每个二级{}对应一个主从复制集群,在每个集群中,可以读组和写组,则就可将读请求调度到读组,将写请求调度到写组,实现读写分离。
本实验中主节点172.18.0.67属于0组,从节点172.18.0.68属于1组,读请求将被调度到172.18.0.68,写请求将被调度到172.18.0.67
MHA实现主节点高可用
对MySQL的主从复制集群,仅有主节点可以接收写请求,在实现了读写分离后,主节点为单点的问题依然存在。一旦主节点故障,将意味着服务器只能接收读请求,不能接收写请求。MHA是一款可实现MySQL主从复制架构中主节点高可用的开源软件。
在监控到主节点故障时,MHA将提升具有最新数据的从节点Latest slave为新的主节点。但是可能出现的情形是,其他从节点具有Latest slave所缺失的数据,所以MHA还会将其他从节点上的这部分数据发送到Latest slave,以提高数据的一致性。
下面将通过一个简单的实验来介绍MHA实现MySQL主节点高可用的配置:
实验环境:
node4(172.18.0.67):主节点
node4(172.18.0.68):从节点1
node4(172.18.0.69):从节点2
node4(172.18.0.70):manager
1 实验准备
确保各节点之间可以不依赖于dns服务器就可以解析主机名
2 ssh无密钥通信环境配置
MHA集群各节点间需要建立ssh连接,实现ssh无密钥通信环境。
生成密钥对儿
私钥文件:id_rsa
公钥文件:id_rsa.pub
若authorized_keys文件已存在,也可以直接cat id_rsa >> authorized_keys,执行结果与执行ssh-copy-id命令相同
将id_rsa、id_rsa.pub、authorized_keys拷贝给其他三个节点,就可以实现任意一个节点与其他三个节点间的ssh无密钥连接,不需要每个节点都生成id_rsa、id_rsa.pub、authorized_keys
连上去执行一个命令,node2与其他三个节点间的ssh无密钥连接成功
3 主从复制集群环境
主节点启用二进制日志、中继日志(因为主节点有可能成为从节点)
从节点
启用中继日志
启用二进制日志,因为从节点有可能成为主节点
relay_log_purge=on禁止修剪中继日志,从节点默认修剪重放完成后的中继日志,为了判定从节点与主节点之间的距离以及将某些内容合并给距离最近的从节点,需禁止修剪中继日志
read_only=on只读,即从节点不接收来自客户端的写请求,对数据文件的修改仅来自于重放主节点的操作
在当前主节点上创建repluser,以便从节点使用该账号连接到当前主节点进行复制。
在当前主节点上创建mhaadmin,以便mha manager使用该账号连接到当前主节点进行mha集群管理(mha manager和各mysql服务器上都安装了node,它们之间不是通过node通信吗?)
从节点也需要repluser,因为从节点可能成为主节点,当其成为主节点时,从节点会使用该账号连接到当前主节点
从节点也需要mhaadmin,以便mha manager使用该账号连接到从节点进行mha集群管理
所以从节点从主节点二进制日志003的245行开始复制
从节点指向主节点
4 MHA集群配置
MHA最新程序包可从该地址下载:
https://code.google.com/p/mysql-master-ha/wiki/Downloads?tm=2
manager节点:安装manager、node程序包
mysql集群各节点:安装node程序包
创建配置文件
user=mhaadmin manager连接后端mysql服务器的管理账号
password=mhapass manager连接后端mysql服务器管理账号的密码
manager_workdir=/data/masterha/appl1 工作目录
manager_log=/data/masterha/appl1 日志目录
remote_workdir=/data/masterha/app1/各node节点的工作目录
ssh_user=root 各节点使用ssh无密钥连接其他节点时的账号
repl_user=repluser 拥有复制权限的账号
repl_password=replpass 拥有复制权限的账号密码
ping_interval=1 每隔多久发起ping操作
定义后端mysql集群的主机
candidate_master=1表示当前主机是候选主机
no_maser=1表示当前主机不是候选主机
ssh无密钥通信环境检测正常
主从复制集群检测正常
ssh无密钥通信检测、主从复制集群检测成功后就可以启动manager,上图中是以前台方式启动的,也可用nohup以后台方式启动,启动后若主节点故障,manager进程就会自动退出,将主节点修复上线、主从复制集群检测成功后,需要再次手动启动
主节点停止服务,模拟主节点故障
manager进程自动退出
查看从节点1(node2,172.18.0.68),已没有从节点状态
只有主节点状态,即已成为主节点,二进制日志位置为003的395
从节点2(node3,172.18.0.69)的主节点已变为node2(172.18.0.68)
主从复制集群检测失败因为原主节点的配置文件不符合条件
启用中继日志
启用二进制日志,因为从节点有可能成为主节点
relay_log_purge=on禁止修剪中继日志,从节点默认修剪重放完成后的中继日志,为了判定从节点与主节点之间的距离以及将某些内容合并给距离最近的从节点,需禁止修剪中继日志
read_only=on只读,即从节点不接收来自客户端的写请求,对数据文件的修改仅来自于重放主节点的操作
指向新主节点
主从复制集群检测成功
后台启动manager进程