haproxy(8):haproxy代理MySQL要考虑的问题
HaProxy系列文章:http://www.cnblogs.com/f-ck-need-u/p/7576137.html
haproxy可以通过 TCP协议 来代理MySQL。但是两个问题必须考虑:
- 后端MySQL的健康检查问题
- 如何保证事务的持久性(同一个事务中的语句路由到同一个后端)
1.1 健康检查问题
haproxy默认已支持MySQL的健康检查,对应的指令为option mysql-check
,浏览下该指令语法:
option mysql-check [ user <username> [ post-41 ] ]
其中user是连接MySQL时使用的用户名,post-41是发送一种名为post v4.1的检查包。整个过程只检查haproxy能否连接到MySQL。
有时候,仅仅检查MySQL服务的连通性是不够的,例如想检查某个数据库是否存在,检查主从复制是否正常,节点是否read_only,某个slave是否严重落后于master等等。目前为止,MySQL组复制(MGR)、Galera已经逐渐普及,haproxy更无法检查这两类集群的合理性。
这时候需要使用外部脚本,自定义检查内容并将检查结果报告给haproxy。当然,借助脚本实现一些自定义的内部操作也是可以的。
因为haproxy对http的支持最完善,因此采用httpchk的健康检查方式,所以使用外部健康检查脚本时,检查结果必须要转换为haproxy能理解的http状态码报告。一般情况下,健康的结果使用http 200状态码表示,不健康的结果使用Http 503来表示 。
1.1.1 MySQL健康检查脚本示例
例如,要检查数据库mytest是否存在,外部的脚本(假设脚本名为/usr/bin/mysqlchk.sh)内容大概如下:
#!/bin/bash
# $0:/usr/bin/mysqlchk.sh
mysql_port=3306
mysql_host="localhost"
chk_mysqluser="haproxychk"
chk_mysqlpasswd="haproxychkpassword1!"
mysql=/usr/bin/mysql
to_test_db=mytest
### check
mysql -u${chk_mysqluser} -p${chk_mysqlpasswd} -h${mysql_host} -P${mysql_port} \
-e "show databases;" 2>/dev/null | grep "${to_test_db}" &>/dev/null
### translate the result to report to haproxy
if [ $? -eq 0 ];then
# mysql is healthy, return http 200
/bin/echo -en "HTTP/1.1 200 OK\r\n"
/bin/echo -en "Content-Type: Content-Type: text/plain\r\n"
/bin/echo -en "Connection: close\r\n"
/bin/echo -en "\r\n"
/bin/echo -en "MySQL is running and $to_test_db exists.\r\n"
/bin/echo -en "\r\n"
sleep 0.1
exit 0
else
# mysql is unhealthy, return http 503
/bin/echo -en "HTTP/1.1 503 Service Unavailable\r\n"
/bin/echo -en "Content-Type: Content-Type: text/plain\r\n"
/bin/echo -en "Connection: close\r\n"
/bin/echo -en "\r\n"
/bin/echo -en "MySQL is down or $to_test_db not exists.\r\n"
/bin/echo -en "\r\n"
exit 1
fi
执行权限:
chmod +x /usr/bin/mysqlchk.sh
然后,将其放进xinetd中进行管理。
yum -y install xinetd
cat /etc/xinetd.d/mysqlchk
# default: on
# description: /usr/bin/mysqlchk.sh
service mysqlchk
{
disable = no
flags = REUSE
socket_type = stream
type = UNLISTED
port = 9200
wait = no
user = nobody
server = /usr/bin/mysqlchk.sh
# server_args = arguments pass to mysqlchk.sh
log_on_failure += USERID
only_from = 0.0.0.0/0
per_source = UNLIMITED
然后向/etc/services中添加端口和服务名映射关系:
cat >>/etc/services<<eof
mysqlchk 9200/tcp #mysqlchk
eof
最后重新启动xinetd:
service xinetd restart
然后配置haproxy,大概内容如下:
listen mysql-cluster 0.0.0.0:3306
mode tcp
balance roundrobin
option httpchk # 注意此处是httpchk,不是mysql-check
server db01 10.4.29.100:3306 check port 9200 inter 12000 rise 3 fall 3
server db02 10.4.29.99:3306 check port 9200 inter 12000 rise 3 fall 3
server db03 10.4.29.98:3306 check port 9200 inter 12000 rise 3 fall 3
其实,这个外部检查脚本是根据Google论坛里的一篇帖子引申出来的(源地址:https://groups.google.com/forum/#!topic/codership-team/RO5ZyLnEWKo)。这种检查方式已经被percona官方采纳并进行了完善,放进了percona-xtradb-cluster包中作为haproxy+PXC的健康检查脚本。
根据这种模式,可以让haproxy检查更多类型的服务。
1.2 事务持久性问题
haproxy代理MySQL的时候,事务持久性的问题必须解决。这个事务持久性不是ACID的D(持久性, Durability),而是transaction persistent,这里简单描述一下此处的事务持久性。
客户端显式开启一个事务,然后执行几个操作,然后提交或回滚。
start transaction
update1...
update2...
insert3...
commit
如果使用代理软件(例如haproxy)对MySQL进行代理,必须要保证这5个语句全都路由到同一个MySQL节点上,即使后端的MySQL采用的多主模型(组复制、Galera都提供多主模型),否则事务中各语句分散,轻则返回失败,重则数据不一致、提交混乱。
这就是transaction persistent的概念:让同一个事务路由到同一个后端节点。
haproxy如何保证事务持久性?对于非MySQL协议感知的代理(lvs/nginx/haproxy等),要保证事务持久性,只能通过间接的方法实现,比较通用的方法是在代理软件上监听不同端口。具体思路如下:
- 1.在haproxy上监听不同端口,例如3307端口的请求作为写端口,3306端口的请求作为读端口。
- 2.从后端MySQL节点中选一个节点(只能是一个)作为逻辑写节点,haproxy将3307端口的请求全都路由给这个节点。
- 3.可以在haproxy上配置备用写节点(backup),但3307端口在某一时刻,必须只能有一个写节点。
这样能保证事务的持久性,也能解决一些乐观锁问题。但是,如果后端是多主模型的Galera或MySQL组复制,这样的代理方式将强制变为单主模型,虽然是逻辑上的强制。当然,这并非什么问题,至少到目前为止的开源技术,都建议采用单主模型。
以下是haproxy保证事务持久性的配置示例:
listen haproxy_3306_read_multi
bind *:3306
mode tcp
timeout client 10800s
timeout server 10800s
balance leastconn
option httpchk
option allbackups
default-server port 9200 inter 2s downinter 5s rise 3 fall 2 slowstart 60s maxconn 64 maxqueue 128 weight 100
server galera1 192.168.55.111:3306 check
server galera2 192.168.55.112:3306 check
server galera3 192.168.55.113:3306 check
listen haproxy_3307_write_single
bind *:3307
mode tcp
timeout client 10800s
timeout server 10800s
balance leastconn
option httpchk
option allbackups
default-server port 9200 inter 2s downinter 5s rise 3 fall 2 slowstart 60s maxconn 64 maxqueue 128 weight 100
server galera1 192.168.55.111:3306 check
server galera2 192.168.55.112:3306 check backup
server galera3 192.168.55.113:3306 check backup
上面的配置通过3306端口和3307端口进行读写分离,并且在负责写的3307中只有一个节点可写,其余两个节点作为backup节点。
对于MySQL的负载来说,更建议采用MySQL协议感知的程序来实现,例如mysql router,proxysql,maxscale,mycat等等数据库中间件。
haproxy(8):haproxy代理MySQL要考虑的问题的更多相关文章
- haproxy(单机)+mysql集群负载均衡
HAProxy是 七层代理 ,在使甠HAProxy后,在MySQL上 看不到Apps的源IP地址 ,看到的是HAProxy地址,而 MySQL的权限访问设置是和IP地址有关 ,这样就导致了MySQL无 ...
- 高可用Mysql架构_Mycat集群部署(HAProxy + 两台Mycat+Mysql双主双从)
既然大家都知道了Mysql分布式在大型网站架构中的作用,在这里就不再阐述.本片博客文章是基于我曾经搭建过的一个Mysql集群基础上实现的,实现过双主热备.读写分离.分库分表. 博客链接:http:// ...
- 【架构】How To Use HAProxy to Set Up MySQL Load Balancing
How To Use HAProxy to Set Up MySQL Load Balancing Dec 2, 2013 MySQL, Scaling, Server Optimization U ...
- nginx对比haproxy 的反向代理
-bash-4.1# ip add | grep inet inet 172.17.0.7/16 scope global eth0 inet6 fe80::42:acff:fe11:7/64 sco ...
- Haproxy全透明代理
1. 系统环境搭建 操作系统Centos7 内核版本3.10 Centos7已自带TPROXY模块,不需要安装TPROXY 2. Haproxy下载,编译,安装,配置 下载地址 http://www. ...
- haproxy 作为反向代理被攻击
在工作中.遇到过一个情况就是我们的额网站被某一个网站攻击 页面结果来自于https://i.umeng.com/? (友盟+) 我这里用的是haproxy作为反向代理. 所以这里我就从haproxy这 ...
- 使用 HAProxy, PHP, Redis 和 MySQL 轻松构建每周上亿请求Web站点
国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...
- haproxy简单配制for mysql
1:下载haproxy 官网:http://www.haproxy.org/ 下载地址:http://www.haproxy.org/download/1.7/src/haproxy-1.7.8.ta ...
- haproxy tcp 反向代理
配置如下: global log 127.0.0.1 local3 warning nbproc 1 maxconn 65535 daemon defaults log global option d ...
随机推荐
- eclipse中补齐代码的快捷键
Shift+Alt+L比如我输入new TextView(this);按这个快捷键能自动生成TextView textView=new TextView(this); 例子: 代码将会变成如下:
- cvb源码分析,resful规范,drf,drf序列化组件,95
1 CBV的源码分析 -Class Base View(基于类的视图) -Function Base View(基于函数的视图) -def as_view 类方法 -def view:类方法内部,闭包 ...
- 将表格添加到Word文档中 ,包括表格样式设置
创建 Table 对象并设置其属性 在您将表格插入文档之前,必须创建 Table 对象并设置其属性. 要设置表格的属性,请创建TableProperties对象并为其提供值. TablePropert ...
- jenkins as code 与go语言学习
前言 最近看jenkins as code这个概念在很多文章中提起,持续交付中八大原则也有把一切都放入版本管理,最近准备把我们公司用的一些jenkins上的job的配置也放到git中,由于https: ...
- 如何高效地写CSS--等以后有空多加总结一下
CSS写的并不多,如果从零开始的项目,自己一定想搬砖来得容易点.CSS编写一定有其工程化的方法,来时编写更加有效率. 考虑将CSS的预处理LESS.Sass或Stylus引入,或者将CSS的后处理Po ...
- 关于 this 关键字的使用
package com.jsti.guiyang_01; /* 自定义Phone类 this关键字 代表当前正在调用这个方法(访问成员变量)的对象(实例) 1.在setxxx方法中用来区分成员变量和局 ...
- st表(poj3264)
st表很像线段树,但线段树既能查询和修改,而st表只能查询. 首先我们先用二维数组建立一个表,st[i][j]表内存的是从第i位开始1<<j范围内的best(st[i][j-1],st[i ...
- HashMap内部结构及实现原理
简单介绍 在研究HashMap之前,我们先大概了解下其他数据结构在新增,查找等基础操作执行性能 数组:采用一段连续的存储单元来存储数据.对于指定下标的查找,时间复杂度为O(1):通过给定值进行查找,需 ...
- day_9内存管理
复习 '''文件处理1.操作文件的三步骤 -- 打开文件:硬盘的空间被操作系统持有 | 文件对象被应用程序持续 -- 操作文件:读写操作 -- 释放文件:释放操作系统对硬盘空间的持有 2.基础的读写 ...
- 对js中闭包,作用域,原型的理解
前几天,和朋友聊天,聊到一些js的基础的时候,有一种‘好像知道,好像又不不知道怎么讲的感觉’...于是捡起书,自己理一理,欢迎拍砖. 闭包 理解闭包首先要理解,js垃圾回收机制,也就是当一个函数被执行 ...