视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
MySQL的使用中实现读写分离的教程_MySQL
2020-11-09 20:15:50 责编:小采
文档


mysql-proxy实现读写分离
MySQL Proxy是一个处于你的client端和MySQL server端之间的简单程序,它可以监测、分析或改变它们的通信。它使用灵活,没有,常见的用途包括:负载平衡,故障、查询分析,查询过滤和修改等等。
MySQL Proxy就是这么一个中间层代理,简单的说,MySQL Proxy就是一个连接池,负责将前台应用的连接请求转发给后台的数据库,并且通过使用lua脚本,可以实现复杂的连接控制和过滤,从而实现读写分离和负载平衡。对于应用来说,MySQL Proxy是完全透明的,应用则只需要连接到MySQL Proxy的监听端口即可。当然,这样proxy机器可能成为单点失效,但完全可以使用多个proxy机器做为冗余,在应用服务器的连接池配置中配置到多个proxy的连接参数即可。
MySQL Proxy更强大的一项功能是实现“读写分离”,基本原理是让主数据库处理事务性查询,让从库处理SELECT查询。数据库复制被用来把事务性查询导致的变更同步到集群中的从库。


1、安装mysql-proxy
此处下载安装包http://ftp.ntu.edu.tw/pub/MySQL/Downloads/MySQL-Proxy/
如果是编译安装依赖包有 libevent2 1.x lua 5.1.x glibc2 2.6.0 pkg-config libtool 1.5
这里使用glibc的二进制包解压即可mysql-proxy-0.8.3-linux-glibc2.3-x86-bit.tar.gz

tar -zxvf mysql-proxy-0.8.3-linux-glibc2.3-x86-bit.tar.gz
 mv mysql-proxy-0.8.3-linux-glibc2.3-x86-bit /usr/local/mysql-proxy

2、创建好mysql主从复制

master 192.168.216.133:3306
slave 192.168.216.132:3306

3、配置mysql-proxy
创建mysql-proxy配置文件,配置文件中的所有选择都不能加引号

vim /usr/local/mysql-proxy/mysql-proxy.conf
[mysql-proxy]
 daemon=true #以后台守护进程方式启动
 keepalive=true #当进程故障后自动重启
 log-level=debug #设置日志级别为debug,可以在调试完成后改成info
 log-file=/var/log/mysql-proxy.log #设置日志文件路径
 basedir=/usr/local/mysql-proxy #设置mysql-proxy的家目录
 proxy-address=192.168.216.132:4040 #指定mysql-proxy的监听地址
 proxy-backend-addresses=192.168.216.133:3306 #设置后台主服务器
 proxy-read-only-backend-addresses=192.168.216.132:3306 #设置后台从服务器
 proxy-lua-script=/usr/local/mysql-proxy/share/doc/mysql-proxy/rw-splitting.lua #设置读写分离脚本路径
 admin-address=192.168.216.132:4041 #设置mysql-proxy管理地址,需要家长admin插件
 admin-username=admin #设置登录管理地址用户
 admin-password=admin #设置管理用户密码
 admin-lua-script=/usr/local/mysql-proxy/share/doc/mysql-proxy/admin.lua 
 #设置管理后台lua脚本路径,改脚本默认没有要自动定义

配置完mysql-proxy.conf后需要确保该文件的权限是600,并确保包含个lua脚本
通过配置文件启动mysql-proxy

/usr/local/mysql-proxy/bin/mysql-proxy --plugins=proxy --plugins=admin --defaults-file=mysql-proxy.conf
 --plugins=proxy #指定proxy插件,该配置写入配置文件无法启动
 --plugins=admin #指定admin插件
 --defaults-file=mysql-proxy.conf #指定配置文件

4、启动测试


登录管理地址查看当前状态

mysql -uadmin -padmin -h192.168.216.132 -P4041

两个后端服务器当前状态为unknown是因为没有用户通过mysql-proxy连接到后端

mysql-proxy不对用户做身份验证,而是下身份验证交予后端服务器进行验证的,因此需要在后端服务器上对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

5、相关问题解决
(1)、如果日志中提示 (debug) [network-mysqld.c:1134]: error on a connection (fd: -1 event: 0). closing client connection.

可以修改 rw-splitting.lua中的min_idle_connections = 4和max_idle_connections = 8的只,将其调大

(2)、如果遇到乱码需要调整后端mysql的设置的字符集

[mysqld]
 skip-character-set-client-handshake
 init-connect = 'SET NAMES utf8'
 character_set_server = utf8


mysqlnd_ms实现mysql读写分离
mysqlnd_ms是mysqlnd的一个插件,该插件实现了连接保存和切换、负载均衡、读写分离的功能。要想使用mysqlnd_ms的读写分离功能必须在安装php时使用–with-mysqlnd。mysqlnd实现的功能是可以不需要在php服务器上安装mysql,在php5.3之前编译安装php需要通过–with-mysql=/path/to/mysql指定mysql的安装路径。


1、安装mysqlnd_ms模块

tar -zxvf mysqlnd_ms-1.5.2.tgz
 cd mysqlnd_ms-1.5.2
 /usr/local/php/bin/phpize
 ./configure --with-php-config=/usr/local/php/bin/php-config
 make && make install

出现以下类似提示,记录下面的路径需要拥有配置php.ini

Installing shared extensions: /usr/local/php/lib/php/extensions/no-debug-non-zts-20121212/
Installing header files: /usr/local/php/include/php/

2、编辑 /usr/local/php/etc/php.ini

extension = /usr/local/php/lib/php/extensions/no-debug-non-zts-20121212/mysqlnd_ms.so
 mysqlnd_ms.enable = On
 mysqlnd_ms.config_file = /usr/local/php/etc/mysqlnd_ms_plugin.ini

3、创建mysqlnd_ms_plugin.ini配置文件

{
 "myapp": {
 "master": {
 "master_0": {
 "host": "192.168.6.135",
 "socket": "\/tmp\/mysql.sock"
 }
 "slave": {
 "slave_0": {
 "host": "192.168.6.136",
 "port": "3306"
 "slave_1": {
 "host": "192.168.6.137",
 "port": "3306"
 "filters": {
 "random": {
 "sticky": "1"
 }
 }
 }
}

这里使用到了1主2从的mysql服务器
filters是定义访问从服务器的策略,random是随机选择一台服务器,strick参数设置成1是指将一次请求都指向一台服务器

4、测试
使用wordpress进行测试,编辑配置文件wp-config.php

/** MySQL主机 */
 define('DB_HOST', 'myapp'); #这的myapp是在mysqlnd_ms_plugin.ini中定义的

下载本文
显示全文
专题