MySQL的高可用方案现在如 MHA, Galera, InnoDB Cluster,一旦在上游使用中间件之后,中间件本身可能成为单点。所以本文要介绍的是对于ProxySQL自身高可用的方案对比。 首先ProxySQL自身是通过Angel进程的形式运行,即proxysql如果有崩溃,主进程会自动拉起来。但如果是无响应或者网络故障,则需要另外的机制去做到服务的高可用。本文总结了四种方法。
ProxySQL有关介绍,请参考: http://xgknight.com/2017/04/10/mysql-proxysql-install-config/
1. 与应用一起部署
所有部署应用的地方,都会部署proxysql节点,当这个proxysql挂掉之后,只影响本机的应用。而且不需要多经过一层网络。
但带来的问题是,如果应用节点很多,proxy的数量也会增加:
- 会导致proxysql的配置不容易管理
- proxysql对后端db健康检查的请求成倍增加
- 限制每个用户或后端db的 max_connections 特性用不了
2. 集中式部署,多ip引用
后端一个db集群,对应中间两个以上的 proxysql 节点,前端应用配置多个ip地址,随机挑选一个使用,完全无状态。仅需要多经过一次网络代理。
这种方式的好处是,不需要再对数据库这种基础服务,多引入一个软件来实现高可用(如下节的keepalive或consul),由应用端获取数据库连接的代码逻辑处理。
但是因为proxysql访问地址是写在配置文件里面的,如果一个节点挂掉,随机挑选还是会落地这个失败的节点。所以优化方案是,ip列表里面默认取某一个,失败之后再选取下一个重试。
示例代码:
|
|
上述并不完美,比如可以改用环形数组轮巡,允许重试其它更多的ip。
能不能不进行多IP引用呢?
为了避免后端引用IP的单点,可以将上面第1种和这里的第2中结合起来,改进的部署方案:(见文后参考链接)
即在原来的基础上,App上的proxysql后端,挂的还是ProxySQL集群。
我个人没有验证这样的方案,如果要用需要充分验证proxysql互连的时候,有没有bug。
3. 经典 keepalived
引入keepalived,通过VIP访问两个以上的proxysql节点,既可以减少一次网络传输,又可以实现proxysql自身的高可用,而且甚至不用关心脑裂的问题,因为proxysql配置完全一样,是无状态的,脑裂了也无妨。
你也可能意识到,这种方式一次只能一个proxysql提供服务,另一个proxysql节点始终处于备用状态。如果配合LVS或haproxy做负载均衡,部署架构又会多出一层网络请求,而且越发复杂(VIP不在proxysql节点上漂,而是在两个lvs之间)。
使用keepalived的前提是,局域网允许发组播包。这在阿里云ECS经典网络下是不允许的,如果有其它类似方式,如SLB也是可行的。目前测试环境采用是 haproxy + keepalived 的方式。
4. Consul服务发现
如果上面的方式都不适用,那么可以进一步考虑使用第三方的服务发现组件。
4.1 介绍
Consul用于实现分布式系统的服务发现与配置,我们将所有proxysql节点注册到consul上作为一个服务来提供,由 Consul agent Server 来判断proxysql节点的存活,每个应用节点上都安装 Consul agent Client 来供应用获取可用地址。
这样部署架构的好处是:
- 不需要多一层负载均衡,多一层网络链路
- 不需要部署大量的proxysql节点
- App或者ProxySQL节点上的Consul故障,不影响其它节点。Consul Server集群的天生具备高可用
- ProxySQL故障会被Consul检查到,踢除故障节点,并通知给所有consul agent
- 可以利用Consul的DNS接口实现简单的负载均衡
其实consul所做的与本文第2节的类似:自动提出不可用的节点,只是一个是被动、手动,一个是主动、自动。 下面简单演示一下。
4.2 部署示例
Consul Server节点的安装在此略过,网上有不少文章,直接进入到在ProxySQL节点安装配置Consul。
Consul agent:
- apps-1:
10.0.201.168
- apps-2:
10.0.201.220
- apps-3:
10.0.201.156
ProxySQL node:
每个节点上运行了两个proxysql进程 7033: crm0
, 7133: crm1
- proxysql-1 :
192.168.1.170
- proxysql-2 :
192.168.1.171
配置 proxysql 节点上的Consul
配置 proxysql-1 节点上的Consul:
|
|
启动consul
|
|
查看日志
proxysql-2 节点上的Consul配置根据上面的内容去改。
4.4 使用方式
先来看下效果:
|
|
看到域名 crm0.proxysql.service.consul
解析出来有两个可用地址 192.168.1.170,192.168.1.171,SRV记录还带出了端口信息(其实这里的端口对每个proxysql是固定/已知的,所以可不用SRV记录搜索)。
在应用端想要连接proxysql使用的方式大致有3种:
DNS接口
需要将各自开发语言的DNS解析库嵌入到项目,指定 127.0.0.1:8600 为dns地址来解析上面的 crm0.proxysql.service.consul 域名。这种方式会增加开发的复杂度。
另一种方式是将应用服务器的默认DNS Server配置成本地consul的内置dns地址,并且consul设置 recursors
选项,来处理解析 consul. 以外的域名。这样对运维改动比较大。
|
|
HTTP接口
通过 API 的方式获取services信息:
|
|
可以获取到 crm1 库的proxysql所有健康的 Node 和 Service 信息,然后任取一个使用。
但并不需要每一次访问proxysql都需要请求api,可以定时(如每隔10s)去请求,缓冲在本地或者变量里;在处理数据库连接的时候发现连接ProxySQL错误,则再主动触发一次向Consul请求新的地址,再重连。
需要考虑的是访问API的地址如果是IP,往往也是单点。另者,java这类jvm语言修改配置后往往需要重启,也不简单。
consul-template直接生成数据库连接的配置文件
consul-template通过事先定义好的模板,根据发现服务的健康状态,生成最新可用的配置文件,然后下发。
如果大但的想一下,各个服务或者语言的配置文件并不相同,直接生成一份 hosts 文件是最简单的,然后通过配置管理工具统一下发应用。也不需要关心是否需要重启应用。
consul watch
Consul watch 功能,可以检测到service变化之后,主动调用一个脚本,脚本可以去更新数据库配置信息,根据需要决定是否重启,后者生成hosts。与consul-template思想是相同的。
因为 watch 是通过阻塞式HTTP长连接请求的方式,实时获取到service的监控状态,所以有问题时反馈还比较及时。
|
|
/tmp/consul_watch_test.sh
脚本里或者python,可以做一些更新数据库配置文件、发送邮件等工作。
参考
- https://www.percona.com/blog/2016/09/16/consul-proxysql-mysql-ha/
- https://www.percona.com/blog/2017/01/19/setup-proxysql-for-high-availability-not-single-point-failure/
- https://www.slideshare.net/DerekDowney/proxysql-tutorial-plam-2016 (本文部分图片出自该PPT)
原文连接地址:http://xgknight.com/2017/07/15/mysql-proxysql-ha-consul/