MySQL Proxy处于客户端应用程序和MySQL服务器之间,通过截断、改变并转发客户端和后端数据库之间的通信来实现其功能,这和WinGate 之类的网络代理服务器的基本思想是一样的。代理服务器是和TCP/IP协议打交道,而要理解MySQL Proxy的工作机制,同样要清楚MySQL客户端和服务器之间的通信协议,MySQL Protocol 包括认证和查询两个基本过程:
认证过程包括:
- 客户端向服务器发起连接请求
- 服务器向客户端发送握手信息
- 客户端向服务器发送认证请求
- 服务器向客户端发送认证结果
如果认证通过,则进入查询过程:
- 客户端向服务器发起查询请求
- 服务器向客户端返回查询结果
当然,这只是一个粗略的描述,每个过程中发送的包都是有固定格式的,想详细了解MySQL Protocol的同学,可以去这里 看看。MySQL Proxy要做的,就是介入协议的各个过程。首先MySQL Proxy以服务器的身份接受客户端请求,根据配置对这些请求进行分析处理,然后以客户端的身份转发给相应的后端数据库服务器,再接受服务器的信息,返回给客户端。所以MySQL Proxy需要同时实现客户端和服务器的协议。由于要对客户端发送过来的SQL语句进行分析,还需要包含一个SQL解析器。可以说MySQL Proxy相当于一个轻量级的MySQL了,实际上,MySQL Proxy的admin server是可以接受SQL来查询状态信息的。
MySQL Proxy通过lua 脚本来控制连接转发的机制。主要的函数都是配合MySQL Protocol各个过程的,这一点从函数名上就能看出来:
- connect_server()
- read_handshake()
- read_auth()
- read_auth_result()
- read_query()
- read_query_result()
至于为什么采用lua 脚本语言,我想这是因为MySQL Proxy中采用了wormhole 存储引擎 的关系吧,这个虫洞存储引擎很有意思,数据的存储格式就是一段lua脚本,真是创意无限啊。
原理图:
Amoeba是一个类似MySQL Proxy的分布式数据库中间代理层软件,是由陈思儒开发的一个开源的java项目。其主要功能包括读写分离,垂直分库,水平分库等,经过测试,发现其功能和稳定性都非常的不错,如果需要构架分布式数据库环境,采用Amoeba是一个不错的方案。目前Amoeba一共包括For aladdin,For MySQL和For Oracle三个版本,本文主要关注For MySQL版本的一个读写分离实现。实际上垂直切分和水平切分的架构也相差不大,改动几个配置就可以轻松实现。
下图是一个采用Amoeba的读写分离技术结合MySQL的Master-Slave Replication的一个分布式系统的架构:
Amoeba处于在应用和数据库之间,扮演一个中介的角色,将应用传递过来的SQL语句经过分析后,将写的语句交给Master库执行,将读的语句路由到Slave库执行(当然也可以到Master读,这个完全看配置)。Amoeba实现了简单的负载均衡(采用轮询算法)和Failover。如果配置了多个读的库,则任何一个读的库出现宕机,不会导致整个系统故障,Amoeba能自动将读请求路由到其他可用的库上,当然,写还是单点的依赖于Master数据库的,这个需要通过数据库的切换,或者水平分割等技术来提升Master库的可用性。
Amoeba可以在不同机器上启动多个,并且做同样的配置来进行水平扩展,以分担压力和提升可用性,可以将Amoeba和MySQL装在同一台机器,也可以装在不同的机器上,Amoeba本身不做数据缓存,所以对于内存消耗很少,主要是CPU占用。对于应用来说,图中的三个Amoeba就是三台一模一样的MySQL数据库,连接其中任何一台都是可以的,所以需要在应用端有一个Load balance和Failover的机制,需要连接数据库时从三台中随机挑选一台即可,如果其他任何一台出现故障,则可以自动Failover到剩余的可用机器上。MySQL的JDBC驱动从connector-j 3.17版本起已经提供了这样的负载均衡和故障切换的功能,那么剩下的事情对于应用来说就很简单了,不需要做太多的改动就能搭建一套高可用的MySQL分布式数据库环境,何乐而不为?