基于Keepalived高可用集群的MariaDB读写分离机制实现
一 MariaDB读写分离机制
在实现读写分离机制之前先理解一下三种主从复制方式:
1.异步复制:
MariaDB默认的复制即是异步的,主库在执行完客户端提交的事务后会立即将结果返给给客户端,并不关心从库是否已经接收并处理,这样就会有一个问题,主节点如果挂掉了,此时主上已经提交的事务可能并没有传到从上,如果此时,强行将从提升为主,可能导致新主上的数据不完整。
2.全同步复制:
指当主库执行完一个事务,所有的从库都执行了该事务才返回给客户端。因为需要等待所有从库执行完该事务才能返回,所以全同步复制的性能必然会收到严重的影响。
3.半同步复制:
介于异步复制和全同步复制之间,主库在执行完客户端提交的事务后不是立刻返回给客户端,而是等待至少一个从库接收到并写到relay log中才返回给客户端。相对于异步复制,半同步复制提高了数据的安全性,同时它也造成了一定程度的延迟,这个延迟最少是一个TCP/IP往返的时间。所以,半同步复制最好在低延时的网络中使用。
在本次实验中我们采用一主两从的方式实现MySQL读写分离机制,而在主从复制中采用异步复制和半同复制两种方式来保证数据的安全性和完整性。为了保证读写分离器高可用,还可利用Keepalived实现高可用集群。
二 常用读写分离器的介绍
mysql-proxy:MySQL官方出品;
atlas:奇虎360公司二次开发产品;
amoeba:Alibaba集团开发的可实现读写分离、分片功能的读写分离器;
OneProxy:读写分离框架,由平民架构开发并维护;
ProxySQL:一款高性能读写分离器;
MaxScale:Mariadb官方,稳定可靠,比较有影响力。
本实验我们采用ProxySQL来实现读写分离。
三 架构拓扑图

四 主从复制配置
#分别在三台主从节点配置如下的内容
[root@node1 ~]# vim /etc/my.cnf.d/server.cnf
[mysqld]
skip_name_resolve=ON
innodb_file_per_table=ON
server_id=1
log_bin=mysql-bin
[root@node2 ~]# vim /etc/my.cnf.d/server.cnf
[mysqld]
skip_name_resolve=ON
innodb_file_per_table=ON
server_id=2
relay_log=relay-log
[root@node3 ~]# vim /etc/my.cnf.d/server.cnf
[mysqld]
skip_name_resolve=ON
innodb_file_per_table=ON
server_id=3
relay_log=relay-log
#启动MariaDB服务
[root@node1 ~]# systemctl start mariadb.service
#登入MariaDB
[root@node1 ~]# mysql
MariaDB [(none)]> SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000003 | 245 | | |
+------------------+----------+--------------+------------------+
#创建MariaDB复制账号
MariaDB [(none)]> GRANT REPLICATION SLAVE,REPLICATION CLIENT ON *.* TO 'repluser'@'172.18.67.%' IDENTIFIED BY 'replpass';
#安装半同步主从复制插件并启动主从复制功能
MariaDB [(none)]> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
MariaDB [(none)]> SET @@global.rpl_semi_sync_master_enabled=ON;
#启动MariaDB服务
[root@node2 ~]# systemctl start mariadb.service
#登入MariaDB
[root@node2 ~]# mysql
#安装半同步主从复制插件并启动主从复制功能
MariaDB [(none)]> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
MariaDB [(none)]> set @@global.rpl_semi_sync_slave_enabled=ON;
#配置slave1节点的master节点
MariaDB [(none)]> CHANGE MASTER TO MASTER_HOST='172.18.67.11',MASTER_USER='repluser',MASTER_PASSWORD='replpass',MASTER_LOG_FILE='mysql-bin.000003',MASTER_LOG_POS=442;
MariaDB [(none)]> START SLAVE;
MariaDB [(none)]> SHOW SLAVE STATUS\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 172.18.67.11
Master_User: repluser
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000003
Read_Master_Log_Pos: 422
Relay_Log_File: relay-log.000002
Relay_Log_Pos: 529
Relay_Master_Log_File: mysql-bin.000003
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: 422
Relay_Log_Space: 817
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: 1
#启动MariaDB服务
[root@node3 ~]# systemctl start mariadb.service
#登入MariaDB
[root@node3 ~]# mysql
#配置slave2节点的master节点
MariaDB [(none)]> CHANGE MASTER TO MASTER_HOST='172.18.67.11',MASTER_USER='repluser',MASTER_PASSWORD='replpass',MASTER_LOG_FILE='mysql-bin.000003',MASTER_LOG_POS=442;
MariaDB [(none)]> START SLAVE;
MariaDB [(none)]> SHOW SLAVE STATUS\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 172.18.67.11
Master_User: repluser
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000003
Read_Master_Log_Pos: 422
Relay_Log_File: relay-log.000002
Relay_Log_Pos: 529
Relay_Master_Log_File: mysql-bin.000003
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: 422
Relay_Log_Space: 817
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: 1
#进行测试
[root@node1 ~]# mysql -e "SHOW GLOBAL STATUS LIKE '%semi%'" | grep 'Rpl_semi_sync_master_clients'
Rpl_semi_sync_master_clients 1
#在主节点创建数据库mydb
[root@node1 ~]# mysql -e "CREATE DATABASE mydb;"
#在从节点查看主节点创建的数据库mydb是否复制过来
[root@node2 ~]# mysql -e "SHOW DATABASES;" | grep mydb
mydb
[root@node3 ~]# mysql -e "SHOW DATABASES;" | grep mydb
mydb
#从节点已经将主节点创建的数据库复制过来了
五 读写分离ProxySQL的配置
1.节点一
[root@node4 ~]# vim /etc/proxysql.cnf
datadir="/var/lib/proxysql"
admin_variables=
{
admin_credentials="admin:admin"
mysql_ifaces="127.0.0.1:6032;/tmp/proxysql_admin.sock"
}
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
}
mysql_servers =
(
{
address = "172.18.67.11" # 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.67.12"
port = 3306
hostgroup = 1
status = "ONLINE" # default: ONLINE
weight = 1 # default: 1
compression = 0 # default: 0
},
{
address = "172.18.67.13"
port = 3306
hostgroup = 1
status = "ONLINE" # default: ONLINE
weight = 1 # default: 1
compression = 0 # default: 0
}
)
mysql_users:
(
{
username = "root"
password = "mrlapulga"
default_hostgroup = 0
max_connections=1000
active = 1
}
)
mysql_replication_hostgroups=
(
{
writer_hostgroup=0
reader_hostgroup=1
}
)
#在主节点对用户进行授权:
MariaDB [(none)]> GRANT ALL ON *.* TO 'root'@'172.18.67.%' IDENTIFIED BY 'mrlapulga';
MariaDB [(none)]> FLUSH PRIVILEGES;
#启动读写分离器的节点1
[root@node4 ~]# systemctl start proxysql
#使用管理接口验证:
[root@node4 ~]# mysql -uadmin -h127.0.0.1 -padmin -P6032
MySQL [(none)]> SELECT hostgroup_id,hostname,hostname,status FROM mysql_servers;
+--------------+--------------+--------------+--------+
| hostgroup_id | hostname | hostname | status |
+--------------+--------------+--------------+--------+
| 0 | 172.18.67.11 | 172.18.67.11 | ONLINE |
| 1 | 172.18.67.12 | 172.18.67.12 | ONLINE |
| 1 | 172.18.67.13 | 172.18.67.13 | ONLINE |
+--------------+--------------+--------------+--------+
#测试读操作
[root@node4 ~]# mysql -uroot -pmrlapulga -h 127.0.0.1 -P3306
MySQL [OA]> use mydb;
MySQL [mydb]> DESC tbl1;
+-------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------------------+------+-----+---------+----------------+
| id | tinyint(3) unsigned | NO | PRI | NULL | auto_increment |
| name | char(20) | YES | | NULL | |
+-------+---------------------+------+-----+---------+----------------+
#测试写操作,在proxysql节点插入一条字段
MySQL [mydb]> INSERT INTO mydb.tbl1 (name) VALUES ('jack');
#在从节点一查看
[root@node2 ~]# mysql -e "SELECT * FROM mydb.tbl1;"
+----+------+
| id | name |
+----+------+
| 1 | jack |
+----+------+
#在从节点二查看
[root@node3 ~]# mysql -e "SELECT * FROM mydb.tbl1;"
+----+------+
| id | name |
+----+------+
| 1 | jack |
+----+------+
2.节点二
#将配置文件复制到ProxySQL节点二
[root@node4 ~]# scp /etc/proxysql.cnf 172.18.67.15:/etc/
#启动节点二的服务
[root@node5 ~]# systemctl start proxysql
六 配置高可用集群
#在ProxySQL1节点配置keepalived
[root@node4 ~]# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email_from keepalived@localhost
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id proxysql
vrrp_macst_group4 224.0.67.67
}
vrrp_instance HA_mysql {
state MASTER
interface eno16777736
virtual_router_id 67
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass lKZvQVv9
}
virtual_ipaddress {
172.18.67.33/16 dev eno16777736
}
}
[root@node4 ~]# systemctl start keepalived
#在ProxySQL2节点配置keepalived
[root@node5 ~]# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email_from keepalived@localhost
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id proxysql
vrrp_macst_group4 224.0.67.67
}
vrrp_instance HA_mysql {
state BACKUP
interface eno16777736
virtual_router_id 67
priority 98
advert_int 1
authentication {
auth_type PASS
auth_pass lKZvQVv9
}
virtual_ipaddress {
172.18.67.33/16 dev eno16777736
}
}
[root@node5 ~]# systemctl start keepalived
七 测试
#在ProxySQL节点1登录MySQL
[root@node4 ~]# mysql -uroot -h172.18.67.33 -pmrlapulga -P 3306
MySQL [(none)]> use mydb;
#查看数据库及表
MySQL [mydb]> SELECT * FROM tbl1;
+----+------+
| id | name |
+----+------+
| 1 | jack |
+----+------+
#在ProxySQL节点2登录MySQL
[root@node5 ~]# mysql -uroot -h172.18.67.33 -pmrlapulga -P 3306
MySQL [(none)]> use mydb;
#查看数据库及表
MySQL [mydb]> SELECT * FROM tbl1;
+----+------+
| id | name |
+----+------+
| 1 | jack |
+----+------+
#测试在ProxySQL1节点写操作
MySQL [mydb]> CREATE TABLE tbl2 (id TINYINT UNSIGNED NOT NULL AUTO_INCREMENT, name CHAR(20) NOT NULL, PRIMARY KEY(id));
#分别在两个从节点查看
[root@node2 ~]# mysql -e "DESC mydb.tbl2;"
+-------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------------------+------+-----+---------+----------------+
| id | tinyint(3) unsigned | NO | PRI | NULL | auto_increment |
| name | char(20) | NO | | NULL | |
+-------+---------------------+------+-----+---------+----------------+
[root@node3 ~]# mysql -e "DESC mydb.tbl2;"
+-------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------------------+------+-----+---------+----------------+
| id | tinyint(3) unsigned | NO | PRI | NULL | auto_increment |
| name | char(20) | NO | | NULL | |
+-------+---------------------+------+-----+---------+----------------+
基于Keepalived高可用集群的MariaDB读写分离机制实现的更多相关文章
- Keepalived高可用集群应用
Keepalived高可用集群应用 1.keepalived服务说明 1.1.keepalived介绍 Keepalived是一个用C语言编写的路由软件.该项目的主要目标是为Linux系统和基于Lin ...
- Haproxy+keepalived高可用集群实战
1.1 Haproxy+keepalived高可用集群实战 随着互联网火热的发展,开源负载均衡器的大量的应用,企业主流软件负载均衡如LVS.Haproxy.Nginx等,各方面性能不亚于硬件负载均衡 ...
- Nginx+Keepalived高可用集群应用实践
Nginx+Keepalived高可用集群应用实践 1.Keepalived高可用软件 1.1 Keepalived服务的三个重要功能 1.1.1管理LVS负载均衡软件 早期的LVS软件,需要通过命令 ...
- Keepalived高可用集群搭建(转载linuxIDC)
1.Keepalived简介 Keepalived是一个基于VRRP协议来实现的WEB服务高可用方案,可以利用其来避免单点故障.使用多台节点安装keepalived.其 他的节点用来提供真实的服务,同 ...
- Linux 笔记 - 第十八章 Linux 集群之(一)Keepalived 高可用集群
一.前言 Linux 集群从功能上可以分为两大类:高可用集群和负载均衡集群.此处只讲高可用集群,负载均衡放在下一篇博客讲解. 高可用集群(High Availability Cluster,简称 HA ...
- rabbitmq+haproxy+keepalived高可用集群环境搭建
1.先安装centos扩展源: # yum -y install epel-release 2.安装erlang运行环境以及rabbitmq # yum install erlang ... # yu ...
- Keepalived高可用集群介绍
1.Keepalived服务介绍 Keepalived起初是专为LVS设计的,专门用来监控LVS集群系统中各个服务节点的状态,后来又加入了VRRP的功能,因此除了配合LVS服务外,也可以为其他服务(n ...
- keepalived高可用集群。
keepalived故障切换转移原理1vrrp协议:(vritual router redundancy protocol)虚拟路由冗余协议,2故障转移.keepalived三大功能1实现物理高可用, ...
- Linux系统——Keepalived高可用集群
#### keepalived服务的三个重要功能1. 管理LVS负载均衡软件Keepalived可以通过读取自身的配置文件,实现通过更底层的接口直接管理LVS的配置以及控制服务的启动,停止功能,这使得 ...
随机推荐
- Linux:finger命令详解
finger 用于查找并显示用户信息 包括本地与远端主机的用户皆可,帐号名称没有大小写的差别. 单独执行finger指令,它会显示本地主机现在所有的用户的登陆信息,包括帐号名称,真实姓名,登入终端机, ...
- linux生成随机密码的十种方法
Linux操作系统的一大优点是对于同样一件事情,你可以使用高达数百种方法来实现它.例如,你可以通过数十种方法来生成随机密码.本文将介绍生成随机密码的十种方法. 1. 使用SHA算法来加密日期,并输出结 ...
- 【机器学习PAI实践十】深度学习Caffe框架实现图像分类的模型训练
背景 我们在之前的文章中介绍过如何通过PAI内置的TensorFlow框架实验基于Cifar10的图像分类,文章链接:https://yq.aliyun.com/articles/72841.使用Te ...
- 我也说说Emacs吧(6) - Lisp速成
前面我们学习了基本操作,也走马观花地看了不少emacs lisp的代码.这一章我们做一个lisp的速成讲座. Lisp的含义是表处理语言.它的代码组成结构都是用括号组成的表来表示的.Lisp中的功能, ...
- 用vue实现百度搜索功能
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- (腾讯视频)iOS开发之视频根据url获取第一帧图片,获取任一帧图片
#import <AVFoundation/AVFoundation.h> + (UIImage*) thumbnailImageForVideo:(NSURL *)videoURL at ...
- OpenFlow技术白皮书-V1.0
1. 概述 OpenFlow是由斯坦福大学的Nick McKeown教授在2008年4月ACM Communications Review上发表的一篇论文OpenFlow: enabling inn ...
- vuex(三)actions
actions:既然mutations只能处理同步函数,我大js全靠‘异步回调’吃饭,怎么能没有异步,于是actions出现了... actions和mutations的区别 1.Acti ...
- 【剑指offer】数组中的逆序对。C++实现
原创文章,转载请注明出处! 博客文章索引地址 博客文章中代码的github地址 # 题目 # 思路 基于归并排序的思想统计逆序对:先把数组分割成子数组,再子数组合并的过程中统计逆序对的数目.统计逆序对 ...
- HDU - 6172:Array Challenge (BM线性递推)
题意:给出,三个函数,h,b,a,然后T次询问,每次给出n,求sqrt(an); 思路:不会推,但是感觉a应该是线性的,这个时候我们就可以用BM线性递推,自己求出前几项,然后放到模板里,就可以求了. ...