在拓扑结构中 , ProxySQL部署在应用程序和MySQL集群的中间位置。应用程序向ProxySQL发起SQL语句 , ProxySQL分析收到的SQL语句 , 进行匹配、重写等操作 , 然后路由给后端MySQL集群中的某实例。
如图:

上图描述的是多个application共用一个ProxySQL实例 , 但需求总是多变的。例如有些app比较繁忙 , 我们想要将这些繁忙的app使用的ProxySQL分离出来 , 让不同的application独立使用一个ProxySQL甚至一个ProxySQL集群 , 让那些不太繁忙的app共用一个ProxySQL。这种情形如下图:

还可以为每个app都配置一个ProxySQL , 如下图。

这种配置的好处是明显的 , 没有单点故障 , 不需要额外的负载均衡 , app+proxysql的节点可以轻松扩展。但是 , 也有缺点 , 各ProxySQL之间无法共享查询缓存。但无论如何 , 这是一种良好的配置方式。
此外 , 还可以使用多层结构 , 对ProxySQL群进行负载均衡。如下图:
.png)
上图几个注意点:
负载软件层 , 也可以使用
ProxySQL对ProxySQL集群进行负载均衡 , 因为ProxySQL自身就是一个代理 , 而且是专门负责MySQL协议的代理。在负载均衡层 , 要保证事务持久 , 不能让一个事务内的不同语句路由到不同的目标上 , 也就是说负载的目标是"有状态"的。因此在使用
lvs/haproxy时 , 必须想办法保证事务持久性。通用性方法是 , 从多个ProxySQL节点中取出一个作为逻辑写节点(可以有backup) ,haproxy/lvs通过端口(也可以用户名 , 但通常采用端口)代理的方式 , 强制将所有写语句路由到这个固定的ProxySQL节点上。而通过
ProxySQL来代理ProxySQL集群 , 因为ProxySQL内部支持事务持久(在mysql_users表中字段transaction_persistent控制持久性)。
综上分析 , 通过lvs/haproxy负载ProxySQL或者负载MySQL、Galera、组复制等 , 实非良策。而ProxySQL因其MySQL协议感知 , 完全能胜任这样的负载工作。
无论如何 , 当有多个ProxySQL实例构成一个集群时 , 需要解决的问题是:如何保证ProxySQL的可用性、如何同步集群中各ProxySQL实例的配置。
目前ProxySQL原生集群功能还在研究当中 , 在原生集群(ProxySQL Cluster)功能中 , 使用master、候选master和slave的概念 , master和候选master负责投票 , 负责写入、更改配置 , 并同步到集群中的其它节点。master故障后 , 还可以从候选Master中选举一个新的master , 如下两图。这些特性能保证ProxySQL集群的可用性、伸缩性。


但是现在,在试验阶段步入稳定可用阶段之前,如何保证ProxySQL的可用性?只能借助第三方工具实现,例如:
keepalived保证第一层次的代理高可用,缺点是可能会浪费一台机器(除非使用VRRP多实例的互为主从结构);ZooKeeper,ZooKeeper实现的分布式锁服务,可以人为进行master选举,从而协调整个ProxySQL集群。
这两种方案的拓扑图如下:


至于如何保证配置文件的同步性,其实这个不是大问题,只要通过管理工具,集群内的所有ProxySQL实例都以完全相同的配置启动,并以批量管理工具(如ansible/salt)来管理各实例,那么配置同步问题就没有多大问题。
但是需要注意,有些时候ProxySQL内部会自动执行load to runtime,例如某ProxySQL实例发现某个MySQL Server节点拖后腿(replication lag),会临时避开这个节点,这时会在内部更改配置并load to runtime。这样内部自动更改的配置如何同步到其它ProxySQL实例上去?其实这类内部更改无需同步,因为所有ProxySQL实例都在监控着后端,一个ProxySQL实例发现了问题,其它ProxySQL实例在极短的时间内也一定会发现问题并自动重新配置。
关于ProxySQL的集群拓扑,大概抛完砖了。经过上面的初步分析,ProxySQL可以结合app部署,可以部署单层ProxySQL群,可以部署多层ProxySQL群,还可以相互结合起来部署。可见,ProxySQL的部署方式非常灵活,能实现的需求也很有弹性,具体如何实现,就看自己的了。
参考链接