Chinaunix首页 | 论坛 | 博客
  • 博客访问: 609259
  • 博文数量: 244
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 130
  • 用 户 组: 普通用户
  • 注册时间: 2016-06-27 09:53
个人简介

记录学习,记录成长

文章分类

全部博文(244)

我的朋友

分类: LINUX

2015-12-29 11:05:48

一.mysql-proxy工作原理
1.基本原理
mysql-proxy处于mysql  client和mysql  server之间,通过截断,改变并转发客户端的查询请求等然后代理和后端数据库之间的通信来实现其主要功能 ;


2.mysql网络通信工作流程
2.1连接阶段


(1)客户端主动连接(connection())服务端,tcp三次握手成功建立tcp连接;
(2)服务端向客户端发起认证初始化连接请求(协议为普通应用层协议);
(3)客户端向服务器发送登陆认证信息;
(4)服务端向客户端返回认证结果;


2.2query阶段



(1)客户端向服务器发送查询请求;
(2)服务器向客户端返回查询结果;


3.mysql-proxy的工作
mysql-proxy工作与client和server之间,对于二者而言是透明的


首先mysql-proxy以服务器的身份接受客户端请求,根据配置对这些请求进行分析处理,然后以客户端的身份转发给相应的后端数据库服务器;
再接受服务器的处理信息,返回给客户端,所以MySQL Proxy需要同时实现客户端和服务器的协议;
由于要对客户端发送过来的SQL语句进行分析,还需要包含一个SQL解析器。可以说mysql-proxy相当于一个轻量级的MySQL了,实际上MySQL Proxy的admin server是可以接受SQL来查询状态信息的;


4.mysql-proxy工作方式
MySQL Proxy通过lua脚本来控制连接转发,主要的函数都是配合MySQL Protocol各个过程的:
            * connect_server()            #接收到Client的连接请求时调用

            * read_handshake()          #读取server发起的handshake信息时调用

            * read_auth()                  #读取Client的认证信息时调用

            * read_auth_result()        #读取认证结果时调用

            * read_query()               #读取Client的query请求时调用

            * read_query_result()     #读取query结果时调用
当Proxy接收到Client请求时,在请求的不同的阶段会调用上面的不同方法;


5.mysql-proxy功能
具体功能:
       1).数据连接的故障转移;

       2).数据连接的负载均衡;

       3).拦截查询(取通信包,实现关键字替换);

       4).重写查询(例如,强制密码度等规则);

       5).添加额外的查询;

       6).删除,修改或者添加返回到客户端的SQL结果集;


二.使用mysql-proxy解决主从延迟 
MySQL的主从同步机制非常方便的解决了高并发读的应用需求,给Web方面开发带来了极大的便利。但这种方式有个比较大的缺陷在于MySQL的同步机制是依赖Slave主动向Master发请求来获取数据的,而且由于服务器负载、网络拥堵等方面的原因,Master与Slave 之间的数据同步延迟是完全没有保证的。短在1秒内,长则几秒、几十秒甚至更长都有可能; 


由于数据延迟问题的存在,当应用程序在Master上进行数据更新,然后又立刻需要从数据库中读取数据时,这时候如果应用程序从Slave上取数据(这也是当前Web开发的常规做法),就可能出现读取不到期望的数据,造成程序运行异常; 


解决这个问题有多种方式,比如最简单的在所有的insert和update之后,强制sleep几秒钟。这是非常粗鲁的方式,对于更新操作不是很高的中小型系统,此方式基本能解决问题;


另外一种方式是应用程序把被更新的数据保存在本机的内存(或者集中式缓存)中,如果在写入数据完成后需要直接读取数据,则从本机内存中读取。这种方式的缺点是极大的增加了应用程序的复杂度,而且可靠性并不能完全得到保障; 


使用MySQL Proxy可以很方便的解决这个问题。MySQL Proxy是基于MySQL Client 和 MySQL Server之间的代理程序,能够完成对Client所发请求的监控、修改。从Client角度看,通过Proxy访问Server和直接访问Server没有任何区别。对于既有的程序而言,只要把直接被访问的Server的IP地址和端口号换成Proxy的IP地址和端口号就可以;


MySQL Proxy的工作原理也较简单。在Proxy启动时可以指定Proxy所需要使用的lua脚本,在lua脚本中预先实现6个方法: 


    * connect_server()     // 接收到Client的连接请求时调用 
    * read_handshake()     // 
    * read_auth()               // 读取Client的认证信息时调用 
    * read_auth_result() // 读取认证结果时调用 
    * read_query()              // 读取Client的query请求时调用 
    * read_query_result()       // 读取query结果时调用 


当Proxy接收到Client请求时,在请求的不同的阶段会调用上面的不同方法。这样Proxy使用者就可以根据自己的业务需求,自由的实现这6个方法达到目的。 


通过在read_query()中加入代码,我们可以截取出当前的请求是insert、update还是select,然后把 insert和update请求发送到Master中,把select请求发送到Slave中,这样就解决了读写分离的问题。 


在解决了读写分离后,如何解决同步延迟呢? 


方法是在Master上增加一个自增表,这个表仅含有1个的字段。当Master接收到任何数据更新的请求时,均会触发这个触发器,该触发器更新自增表中的记录。如下图所示:





由于Count_table也参与Mysq的主从同步,因此在Master上作的 Update更新也会同步到Slave上。当Client通过Proxy进行数据读取时,Proxy可以先向Master和Slave的 Count_table表发送查询请求,当二者的数据相同时,Proxy可以认定 Master和Slave的数据状态是一致的,然后把select请求发送到Slave服务器上,否则就发送到Master上。如下图所示: 



通过这种方式,就可以比较完美的结果MySQL的同步延迟不可控问题。之所以所“比较完美”,是因为这种方案double了查询请求,对 Master和Slave构成了额外的压力。不过由于Proxy与真实的Mysql Server采用连接池的方式连接,因此额外的压力还是可以接受的。




参考资料:
http://www.cnblogs.com/itech/archive/2011/09/22/2185365.html

http://blog.itpub.net/15480802/viewspace-1432659/
阅读(1310) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~