Mysql Proxy 简介
MySQL Proxy是一个处于你的client端和MySQL server端之间的简单程序,它可以监测、分析、或改变它们的通信。它使用灵活,没有限制,常见的用途包括:负载平衡,故障、查询分析,查询过滤或修改等等。
MySQL Proxy就是这么一个中间层代理,简单的说,MySQL Proxy就是一个连接池,负责前台应用的连接请求转发给后台的数据库,并且通过使用lua脚本,可以实现复杂的连接控制和过滤,从而实现读写分离和负载平衡。对于应用来说,MySQL Proxy是完全透明的,应用则只需要连接到MySQL Proxy的监听端口即可。当然,这样proxy机器可能成为单点故障,但完全可以使用多个proxy机器做冗余,在应用服务器和连接池配置中配置多个proxy的连接参数即可。
MySQL Proxy更强大的一项功能就是实现"读写分离",基本原理就是让主数据库处理事务性查询,让从服务器进行SELECT查询。数据库复制被用来把事务性查询导致的变更同步到集群的从库中。
MySQL Proxy安装方式
一、源码安装
1、源码安装时,MySQL proxy的依赖关系:
libevent 1.x or higher
lua 5.1x or higher
glib2 2.6.0 or higher
pkg-config.
libtool 1.5 or higher
MySQL 5.0.x or higher developer files
2、安装
# tar xf mysql-proxy-0.8.2.tar.gz
# cd mysql-proxy-0.8.2
# ./configure
# make
# make check
如果管理员有密码,上面的步骤则需要使用如下格式进行:
#MYSQL_PASSWORD=root_pwd make check
# make install
默认情况下,mysql-proxy安装在/usr/local/sbin/mysql-proxy,而Lua示例脚本安装在/usr/local/share目录中
二 、通用二进制格式安装
1、下载,当前系统架构为 Centos6.5 64位系统
http://mirrors.sohu.com/mysql/MySQL-Proxy/mysql-proxy-0.8.4-linux-el6-x86-64bit.tar.gz
2、解压
#tar xf mysql-proxy-0.8.4-linux-e16-x86-64bit.tar.gz
#mv mysql-proxy-0.8.4-linux-e16-x86-64bit /usr/local/mysql-proxy
3、添加代理用户
# useradd mysql-proxy
4、为mysql-proxy提供SysV服务脚本
5、为mysql-proxy脚本提供配置文件
MySQL Proxy实现读写分离
环境搭建
如上图所示
MySQL Master 主服务器 | 172.16.13.13 | MariaDB-5.5.36 |
MySQL Slave 从服务器 | 172.16.13.14 | MariaDB-5.5.36 |
MySQL Proxy 代理服务器 | 172.16.13.2 | mysql-proxy-0.8.4-linux-el6-x86-64bit.tar.gz |
一、MySQL主从复制架构的实现
关于MySQL主从复制的实现详情请参考我的博客:
http://jungege.blog.51cto.com/4102814/1396276
二、MySQL Proxy服务器配置
1、下载所需要的版本,这里的系统平台为CentOS6.5 64系统
#wget http://mirrors.sohu.com/mysql/MySQL-Proxy/mysql-proxy-0.8.4-linux-el6-x86-64bit.tar.gz # tar xf mysql-proxy-0.8.4-linux-el6-x86-64bit.tar.gz # mv mysql-proxy-0.8.4-linux-el6-x86-64bit /usr/local/mysql-proxy
2、添加代理用户
# useradd mysql-proxy
3、为mysql-proxy提供SysV服务脚本
# vim /etc/rc.d/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
#chmod +x /etc/rc.d/init.d/mysql-proxy 赋予执行权限 #chkconfig --add mysql-proxy 添加到系统服务列表中 #chkconfig mysql-proxy on 开机启动
4、为mysql-proxy服务脚本提供配置文件
#vim /etc/sysconfig/mysql-proxy 内容如下
# Options for 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="" PROXY_USER="mysql-proxy" PROXY_OPTIONS="--daemon --log-level=info --log-use-syslog" PROXY_OPTIONS="--daemon --log-level=info --log-use-syslog --plugins=proxy --plugins=admin --proxy-backend-addresses=172.16.13.13:3306 --proxy-read-only-backend-addresses=172.16.13.14:3306 --proxy-lua-script=/usr/local/mysql-proxy/share/doc/mysql-proxy/rw-splitting.lua" 其中的proxy-backend-addresses选项和proxy-read-only-backend-addresses选项均可重复使用多次,以实现指定多个读写服务器或只读服务器。
mysql-proxy的配置选项
mysql-proxy的配置选项大致可分为帮助选项、管理选项、代理选项及应用程序选项几类,下面一起去介绍他们
--help
--help-admin
--help-proxy
--help-all ——以上四个选项均用于获取帮助信息;
--proxy-address=host:port ——代理服务监听的地址和端口
--admin-address=host:port ——管理模块监听的地址和端口
--proxy-backend-address=host:port ——后端mysql服务器的地址和端口
--proxy-read-only-backend-addresses=host:port ——后端只读mysql服务器的地址和端口
--proxy-lua-script=file_name ——完成mysql代理功能的Lua脚本
--daemon ——以守护进程模式启动mysql-proxy
--keepalive ——在mysql-proxy崩溃时尝试重启之
--log-file=/path/to/log_file_name ——日志文件名称
--log-level=level ——日志级别
--log-use-syslog ——基于syslog记录日志
--plugins=plugin,..——在mysql-proxy启动时加载的插件
--user=user_name ——运行mysql-proxy进程的用户
--defaults-file=/path/to/confi_file_name ——默认使用的配置文件路径;其配置段使用[mysql-proxy]标识
--proxy-skip-profiling ——禁用profile
--pid-file=/path/to/pid_file_name ——进程文件名
5、复制一下内容建立admin.lua文件,将其保存至/user/local/mysql-proxy/share/doc/mysql-proxy
#vim /usr/local/mysql-proxy/share/doc/mysql-proxy/admin.lua 内容如下 --[[ $%BEGINLICENSE%$ Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA $%ENDLICENSE%$ --]] 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
6、测试
6.1 管理功能测试
#service mysql-proxy start
#ss -ntl
管理端口:4041
读写分离端口:3306
[root@www ~]# mysql -uadmin -padmin -h172.16.13.2 --port=4041 Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 1 Server version: 5.0.99-agent-admin Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql>
6.2 读写分离测试
在MySQL 主服务器上授权一个用户 MariaDB [(none)]> grant all on *.* to 'root'@'172.16.13.2' identified by '123';
6.2.1接下来我们在MySQL Proxy服务器(172.16.13.2)上测试
###########多次读写操作,这样效果才能明显如下所示:
[root@www mysql-proxy]# mysql -uroot -h172.16.13.2 -p123 --port=3306 -e "select user from mysql.user" [root@www mysql-proxy]# mysql -uroot -h172.16.13.2 -p123 --port=3306 -e "select user from mysql.user" [root@www mysql-proxy]# mysql -uroot -h172.16.13.2 -p123 --port=3306 -e "create database testdb" 注意:--port=3306不需要带,默认侦听的读写分离连接端口就是3306. 如果将mysql-proxy安装在了一台mysql服务器上,那么MySQL侦听的端口要改为其他端口,否则会冲突(直接在my.cnf配置文件改就行)
6.2.2 多次读写操作后,我们去管理端口查看读写分离情况
[root@www ~]# mysql -uadmin -h172.16.13.2 -padmin --port=4041 mysql> select * from backends; +-------------+-------------------+-------+------+------+-------------------+ | backend_ndx | address | state | type | uuid | connected_clients | +-------------+-------------------+-------+------+------+-------------------+ | 1 | 172.16.13.13:3306 | up | rw | NULL | 0 | | 2 | 172.16.13.14:3306 | up | ro | NULL | 0 | +-------------+-------------------+-------+------+------+-------------------+ 2 rows in set (0.00 sec)
基于mysql-proxy实现了MariaDB主从复制架构中读写分离!
总结:整个实例中不难发现,如果架构为LAMP的架构,那么PHP程序代码直接与MySQL Proxy地址相连即可,MySQL Proxy会将读写代理至后端的MySQL主从复制架构中,MySQL主服务器负责读写,从服务器只负责读,从而实现读写分离架构,如果担心Mysql proxy单点故障,可以建立冗余,多建立几个。
PS:水平有限,如有不妥请指出,MariaDB的MMM架构即将推出,敬请期待!!!