基于Mysql-Proxy 实现MariaDB 读写分离
-
一、Mysql-Proxy 简单介绍
MySQL-Proxy是一个处于你的client端和MySQL server端之间的简单程序,它可以监测、分析或改变它们的通信。它使用灵活,没有限制,常见的用途包括:负载平衡,故障、查询分析,查询过滤和修改等等。
MySQL-Proxy就是这么一个中间层代理,简单的说,MySQL-Proxy就是一个连接池,负责将前台应用的连接请求转发给后台的数据库,并且通过使用lua脚本,可以实现复杂的连接控制和过滤,从而实现读写分离和负载平衡。对于应用来说,MySQL-Proxy是完全透明的,应用则只需要连接到MySQL-Proxy的监听端口即可。当然,这样proxy机器可能成为单点失效,但完全可以使用多个proxy机器做为冗余,在应用服务器的连接池配置中配置到多个proxy的连接参数即可。
MySQL-Proxy更强大的一项功能是实现“读写分离”,基本原理是让主数据库处理事务性查询,让从库处理SELECT查询。数据库复制被用来把事务性查询导致的变更同步到集群中的从库。
二、实验环境
服务器 IP地址 系统版本 master主服务器 172.16.8.8 Centos6.5 slave从服务器 172.16.8.9 Centos6.5 mysql-proxy服务器 172.16.8.5 Centos6.5 3台服务器时间要一致
1# ntpdate
172.16
.
0.1
//同步时间
注,此实验是基于上一篇博客,http://584014981.blog.51cto.com/8605371/1396724 ,先实现主从复制,再实现读写分离。
三、Mysql-Proxy 命令简介
mysql-proxy 命令
--help-all ———— 用于获取全部帮助信息
--proxy-address=host:port ———— 代理服务监听的地址和端口
--admin-address=host:port ———— 管理模块监听的地址和端口
--proxy-backend-addresses=host:port ———— 后端mysql服务器的地址和端口(主服务器)
--proxy-read-only-backend-addresses=host:port —— 后端只读mysql服务器的地址和端口(从服务器)
--proxy-lua-script=file ———— 完成mysql代理功能的Lua脚本
--daemon ———— 以守护进程模式启动mysql-proxy
--defaults-file=/path/to/conf_file_name ———— 默认使用的配置文件路径
--log-file=/path/to/log_file_name ———— 日志文件名称
--log-level=level ———— 日志级别
--log-use-syslog ———— 基于syslog记录日志
--user=user_name ———— 运行mysql-proxy进程的用户
四、Mysql-Proxy主从分离
1.增加代理用户
在Mysql-Proxy服务器上操作:
12[root@node1 ~]# groupadd -g
3306
mysql-proxy
[root@node1 ~]# useradd -u
3306
-g mysql-proxy -s /sbin/nologin -M mysql-proxy
2.安装mysql-proxy
下载地址:
http://pan.baidu.com/s/1sjQ4czV
1234[root@node1 ~]# tar xf mysql-proxy-
0.8
.
3
-linux-glibc2.
3
-x86-64bit.tar.gz -C /usr/local
[root@node1 ~]# cd /usr/local
[root@node1 local]# ln -sv mysql-proxy-
0.8
.
3
-linux-glibc2.
3
-x86-64bit mysql-proxy
[root@node1 local]# cd mysql-proxy
3.修改文件的拥有者与所属组
1[root@node1 mysql-proxy]# chown -R root:mysql-proxy /usr/local/mysql-proxy/*
4.修改PATH环境变量
1234[root@node1 mysql-proxy]# vim /etc/profile.d/mysql-proxy.sh
//添加如下内容:
export PATH=$PATH:/usr/local/mysql-proxy/bin
[root@node1 mysql-proxy]# source /etc/profile
//重读配置文件
5.启动mysql-proxy
1[root@node1 mysql-proxy]# mysql-proxy --daemon --log-level=debug --log-file=/
var
/log/mysql-proxy.log --plugins=
"proxy"
--proxy-backend-addresses=
"172.16.8.8:3306"
--proxy-read-only-backend-addresses=
"172.16.8.9:3306"
#启动mysql-proxy
从日志与进程来看,已经启动成功!
6.在主服务器上创建测试的账号与密码
master:
12MariaDB [(none)]> grant all on *.* to root@
'172.16.8.%'
identified by
'123'
;
MariaDB [(none)]> flush privileges;
7.在从服务上进行测试
slave:
验证是否能通过代理端口4040 端口连接到 mysql-proxy
1[root@station142 ~]# mysql -uroot -p -h172.
16.8
.
5
--port=
4040
注,已经成功从4040端口,连接进mysql-proxy。下面我们来实现读写分离。
8.读写分离
1.Mysql-Proxy本身不会实现读写分离,主要是依靠 Lua 脚本实现的
在mysql-proxy 的安装目录中有一个rw-splitting.lua 脚本,专门用来实现 读写分离,路径是/usr/local/mysql-proxy/share/doc/mysql-proxy/rw-splitting.lua
2.为mysql-proxy 提供一个管理接口,方便以后随时查看后端mysql 服务器的状态和访问类型,实现管理功能
注,下面为大家提供一个管理接口的脚本,同样也是一个LUA 脚本,建议跟读写分离脚本放在同一目录。
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273[root@node1 mysql-proxy]# vim /usr/local/mysql-proxy/share/doc/mysql-proxy/admin.lua
function
set_error(errmsg)
proxy.response = {
type = proxy.MYSQLD_PACKET_ERR,
errmsg = errmsg or
"error"
}
end
function
read_query(packet)
if
packet:byte() ~= proxy.COM_QUERY then
set_error(
"[admin] we only handle text-based queries (COM_QUERY)"
)
return
proxy.PROXY_SEND_RESULT
end
local query = packet:sub(
2
)
local rows = { }
local fields = { }
if
query:lower() ==
"select * from backends"
then
fields = {
{ name =
"backend_ndx"
,
type = proxy.MYSQL_TYPE_LONG },
{ name =
"address"
,
type = proxy.MYSQL_TYPE_STRING },
{ name =
"state"
,
type = proxy.MYSQL_TYPE_STRING },
{ name =
"type"
,
type = proxy.MYSQL_TYPE_STRING },
{ name =
"uuid"
,
type = proxy.MYSQL_TYPE_STRING },
{ name =
"connected_clients"
,
type = proxy.MYSQL_TYPE_LONG },
}
for
i =
1
, #proxy.global.backends
do
local states = {
"unknown"
,
"up"
,
"down"
}
local types = {
"unknown"
,
"rw"
,
"ro"
}
local b = proxy.global.backends[i]
rows[#rows +
1
] = {
i,
b.dst.name, -- configured backend address
states[b.state +
1
], -- the C-id
is
pushed down starting at
0
types[b.type +
1
], -- the C-id
is
pushed down starting at
0
b.uuid, -- the MySQL Server's UUID
if
it
is
managed
b.connected_clients -- currently connected clients
}
end
elseif query:lower() ==
"select * from help"
then
fields = {
{ name =
"command"
,
type = proxy.MYSQL_TYPE_STRING },
{ name =
"description"
,
type = proxy.MYSQL_TYPE_STRING },
}
rows[#rows +
1
] = {
"SELECT * FROM help"
,
"shows this help"
}
rows[#rows +
1
] = {
"SELECT * FROM backends"
,
"lists the backends and their state"
}
else
set_error(
"use 'SELECT * FROM help' to see the supported commands"
)
return
proxy.PROXY_SEND_RESULT
end
proxy.response = {
type = proxy.MYSQLD_PACKET_OK,
resultset = {
fields = fields,
rows = rows
}
}
return
proxy.PROXY_SEND_RESULT
end
3.重新启动mysql-proxy
注,这次启动要添加以下启动选项 ,因为我们添加了额外的插件,把新加功能添加进来,选项如下。
--plugins=admin 在mysql-proxy启动时加载的插件;
--admin-username="admin" 运行mysql-proxy进程管理的用户;
--admin-password="admin" 密码
--admin-lua-script="/usr/local/mysql-proxy/share/doc/mysql-proxy/admin.lua" 插件使用的配置文件路径;
先把原来的连接kill掉,再程序启动
12[root@node1 mysql-proxy]# killall mysql-proxy
[root@node1 mysql-proxy]# mysql-proxy --daemon --log-level=debug --log-file=/
var
/log/mysql-proxy.log --plugins=
"proxy"
--proxy-backend-addresses=
"172.16.8.8:3306"
--proxy-read-only-backend-addresses=
"172.16.8.9:3306"
--proxy-lua-script=
" /usr/local/mysql-proxy/share/doc/mysql-proxy/rw-splitting.lua"
--plugins=admin --admin-username=
"admin"
--admin-pass<a
class
=
"keylink"
href=
"http://www.it165.net/edu/ebg/"
target=
"_blank"
rel=
"noopener nofollow"
>word</a>=
"admin"
--admin-lua-script=
"/usr/local/mysql-proxy/share/doc/mysql-proxy/admin.lua"
4.在slave测试一下,记得使用管理端口4041 登陆,密码是admin。
12[root@station142 ~]# mysql -uadmin -p -h172.
16.8
.
5
--port=
4041
//密码为admin
MySQL [(none)]> select * from backends;
//查看读写分离状态
注,大家可以看到状态信息是unknown,因为我们还没有执行读写操作,所有状态还有UP起来,下面我们来测试一下读写信息,再来查看状态。
5.执行一下读写操作
123[root@station142 mysql]# mysql -uroot -p123 -h172.
16.8
.
5
--port=
4040
-e
"create database wowo"
[root@station142 mysql]# mysql -uroot -p123 -h172.
16.8
.
5
--port=
4040
-e
"select user from mysql.user"
[root@station142 mysql]# mysql -uroot -p123 -h172.
16.8
.
5
--port=
4040
-e
"select user from mysql.user"
6.再次查看一下读写分离状态
12[root@station142 ~]# mysql -uadmin -padmin -h172.
16.8
.
5
--port=
4041
MySQL [(none)]> select * from backends;
注,大家可以看到,这时状态全部是up。说明读写分离配置成功。 在测试读写分离的时候,我们可以分布测试,比如先测试读的语句,查看读写状态是否UP ,然后在测试写的语句。反反复复多测试几次才能看出效果 。
五、优化启动脚本,并修改连接端口
每次启动的时候,启动选项非常多,一不小心都会写错,所以我们创建一个脚本或者配置文件把选项都写进去,每次启动的时候都调用此脚本。
(1).增加配置文件
123456789[root@node1 mysql-proxy]# vim /etc/sysconfig/mysql-proxy
//添加如下内容
ADMIN_USER=
"admin"
ADMIN_PASSWORD=
"admin"
ADMIN_ADDRESS=
""
ADMIN_LUA_SCRIPT=
"/usr/local/mysql-proxy/share/doc/mysql-proxy/admin.lua"
PROXY_ADDRESS=
"0.0.0.0:3306"
PROXY_USER=
"mysql-proxy"
PROXY_OPTIONS=
"--daemon --log-level=info --log-file="
/
var
/log/mysql-proxy.log
" --plugins=proxy --plugins=admin --proxy-backend-addresses=172.16.8.8:3306 --proxy-read-only-backend-addresses=172.16.8.9:3306 --proxy-lua-script=/usr/local/mysql-proxy/share/doc/mysql-proxy/rw-splitting.lua"
(2).增加sysV脚本
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576[root@node1 mysql-proxy]# vim /etc/init.d/mysql-proxy
//添加如下内容:
#!/bin/bash
#
# mysql-proxy This script starts and stops the mysql-proxy daemon
#
# chkconfig: -
78
30
# processname: mysql-proxy
# description: mysql-proxy
is
a proxy daemon
for
mysql
# Source
function
library.
. /etc/rc.d/init.d/functions
prog=
"/usr/local/mysql-proxy/bin/mysql-proxy"
# Source networking configuration.
if
[ -f /etc/sysconfig/network ]; then
. /etc/sysconfig/network
fi
# Check that networking
is
up.
[ ${NETWORKING} =
"no"
] && exit
0
# Set
default
mysql-proxy configuration.
ADMIN_USER=
"admin"
ADMIN_PASSWD=
"admin"
ADMIN_LUA_SCRIPT=
"/usr/local/mysql-proxy/share/doc/mysql-proxy/admin.lua"
PROXY_OPTIONS=
"--daemon"
PROXY_PID=/
var
/run/mysql-proxy.pid
PROXY_USER=
"mysql-proxy"
# Source mysql-proxy configuration.
if
[ -f /etc/sysconfig/mysql-proxy ]; then
. /etc/sysconfig/mysql-proxy
fi
RETVAL=
0
start() {
echo -n $
"Starting $prog: "
daemon $prog $PROXY_OPTIONS --pid-file=$PROXY_PID --proxy-address=
"$PROXY_ADDRESS"
--user=$PROXY_USER --admin-username=
"$ADMIN_USER"
--admin-lua-script=
"$ADMIN_LUA_SCRIPT"
--admin-password=
"$ADMIN_PASSWORD"
RETVAL=$?
echo
if
[ $RETVAL -eq
0
]; then
touch /
var
/lock/subsys/mysql-proxy
fi
}
stop() {
echo -n $
"Stopping $prog: "
killproc -p $PROXY_PID -d
3
$prog
RETVAL=$?
echo
if
[ $RETVAL -eq
0
]; then
rm -f /
var
/lock/subsys/mysql-proxy
rm -f $PROXY_PID
fi
}
# See how we were called.
case
"$1"
in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
condrestart|
try
-restart)
if
status -p $PROXY_PIDFILE $prog >&/dev/
null
; then
stop
start
fi
;;
status)
status -p $PROXY_PID $prog
;;
*)
echo
"Usage: $0 {start|stop|restart|reload|status|condrestart|try-restart}"
RETVAL=
1
;;
esac
exit $RETVAL
给mysql-proxy执行权限并且添加进服务
12[root@node1 mysql-proxy]# chmod +x /etc/rc.d/init.d/mysql-proxy
[root@node1 mysql-proxy]# chkconfig --add mysql-proxy
(3).启动测试脚本
12[root@node1 mysql-proxy]# killall mysql-proxy
//先关闭mysql-proxy
[root@node1 mysql-proxy]# service mysql-proxy start
//启动mysql-proxy
(5).测试连接一下
大家可以看到,现在连接不用指定端口,默认使用3306端口。好了,到这里mysql-proxy实现读写分离配置全部完成!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
2014-01-10 MySQL prepare语句的SQL语法