《基于mysql的数据库集群系统的实现》由会员分享,可在线阅读,更多相关《基于mysql的数据库集群系统的实现(9页珍藏版)》请在金锄头文库上搜索。
1、基于 MySQL 的数据库集群系统的实现您的 WebApp 系统是否正在使用一个 MySQL 的数据库系统?您的客户是不是总是抱怨页面结果反馈的非常慢?您的 MySQL 系统的负载是不是总是维持在一个非常高的状态下?本文将为您提供一个分担MySQL 系统的负载的方法,以及由此派生出来的一个 MySQL-HA-Proxy 的开发项目。使用本文提供的方法,您将以最小的源代码改动,获得 MySQL 系统的高效运转。第一节 数据库集群技术的现状目前数据库集群系统应用得比较成功,应用范围比较广泛的是:Oracle 公司的 Oracle9 与 IBM 公司DB2。Oracle9 采用 Shared-sto
2、rage 的技术,DB2 选择了 Shared-nothing 的技术,二者各有长短。最新的数据库集群系统的理论基础是分布式计算,将数据分布到每个节点,所有的计算节点并行处理数据,将结果汇总。这样的方式无疑是最完美的。但是目前仍然不能实现全部的功能。对于 Shared-storage 以及 Shared-nothing 的技术请参考 Oracle 以及 IBM 网站上的相关资料。第二节 目前数据库应用状况目前数据库应用状况大致分为两类,第一类是数据量在 100G 以下,数据库访问频繁,请求密集。主要是 Web APP 类型的应用,例如:网站,论坛等。这些 Web APP 类型的应用访问数据库的
3、特点是:访问频繁,数据库每秒钟要接受几千次以上的查询,需要经常追加数据,同时对数据的响应速度要求比较高。另一类是用于科学计算、存储历史数据的应用,数据量往往达到几百 G。这些应用访问数据库的特点是:多为查询操作,数据都是分批、定时、集中倒入数据库,数据库的记录非常多,积累了大量的数据,对数据库的响应速度没有太高要求。第三节 暴露出来的问题第一类应用,由于访问比较频繁,而且为了支持更多的访问,Web Server 一般都使用了负载均衡的集群,但是对于数据库来说,由于无法实现集群操作,每秒钟的请求不断增加,随着服务器负载的增加,响应单个请求的速度越来越慢,如果库文件比较大,出现写操作的时候还会出现
4、锁表时间过长等影响访问效率的事情。第二类应用,主要是数据文件太大,每次处理数据都需要大量的时间,如果写错一个语句就需要花几个小时来重做查询。第四节 如何解决首先应当从硬件、软件、程序、索引、SQL 语句这几个方面进行优化,如果仍然不能解决问题,我们就要考虑数据库系统的集群(并行处理)了。对于第一类的应用,在数据库服务器正常运行,负载不高的情况下,应用对数据库系统的状况还是满意的。但是数据库系统负载过高之后,就会出现完成请求的时间加长,达不到系统的要求时间。既然负载是由于过多的请求造成的,我们就采取分担请求的方式,让一部分的请求去访问另外一台服务器,让单台服务器的负载降低,从而解决问题。对于第二
5、类的应用,就需要分布式计算的系统来解决了,一般的系统是无能为力了。第五节 针对于Linux+Apache+PHP+MySQL 的第一类应用问题的解决方式一个实际案例的解决: 我在工作当中遇到了这样的问题,我们的 Web Server 是 Linux+Apache+Php 的三台机器组成的集群,MySQL 运行在 SUN450,2G 内存的平台上。由于 WEB 的访问量在高峰的时候几乎满负荷运转,LoadAvg(就是一分钟之内处于 Running 状态的进程数量) 都在 10-20 之间,反映出来就是大量的请求都在访问数据库的时候被挂住了,导致一个请求没有完成,下一个请求又进来,最后恶性循环。L
6、oadAvg 会在瞬间飙升至 800 以上。数据库那边就更糟糕了,LoadAvg 达到 300 多,数据库的线程非常多,CPU 忙于切换线程状态,这个时候除非 Restart MySQL,否则怎么都不会好。在对 SQL 语句优化完成后还是不能很好的解决问题,我们增加了一台数据库服务器,通过 MySQL 的数据同步机制,让两台数据库上的数据保持同步,修改了一部分只会发生读取操作的 php 程序,让这些程序连接另外一台数据库,算是把负载分离出去一部分,问题得到了初步的解决。但是后来业务做大,我们又增加了多台服务器,修改了很多程序,分离他们对数据库的读取操作,访问不同的服务器。 回页首回页首第六节
7、MySQL-HA-Proxy 方案的提出通过修改程序的方式实现将系统的负载分离,是件很痛苦的事情,工程浩大,而且不能弄错,因为除了主服务器可以写入、修改数据,而其它的服务器只能通过数据同步更新自身的数据,所以如果你对那些数据库进行了写操作,结果将是灾难性的。如果我们能够有一个程序分拣 SQL 语句,根据他的类型(读取/ 写入),分别传送给不同的服务器,然后再将结果返回。采用一种类似 HTTP 的 PROXY 的方式,这样我们就不需要通过修改源程序的方式来分担负载了,如果再能够根据服务器的负载状况,或者是表的状态(可用/锁定),来判断应该将这个请求分配到哪台服务器,那就比我们修改源程序所能达到的
8、效果还要好。第七节 MySQL Client 与 Server 之间如何通信四处寻找,也没有找到一篇关于 Mysql 通讯协议的文章,看来只有分析 Mysql 的源程序了。于是找来mysql 3.23.49 的代码,打开 sniffer 工具。MySQL 的通讯协议可能变更过多次,在 3.23.49 的版本里面,通讯协议的版本竟然是 10。简单的分析了一下通讯协议,现在规整如下,有些地方还不是很完善,由于我实在没有太多的时间仔细研读 mysql 的代码,目前我只了解到了这些。Server 对 Client 请求的响应数据格式:偏移 区域 类型 长度(byte) 说明0 HEAD1 2 Data
9、 Length 33 FLAG 1=0 普通信息 =1 多段信息 =2 认证返回 2 段结束字 4 DATA CMD Code 1 5 Message DataLength - 1 当 FLAG=0 , 2 的时候 CMD Code 与 Message 的定义CMDCode 类型 Message 的结构00 状态码 偏移 类型 Length(byte) 0 Affect rows 2 0A 服务器版本号 偏移 类型 Length(byte) 只有在刚刚连接上 Server 的时 0 VersionString 8 end of 0回页首回页首 8 Session ID 4 32bits12 U
10、nKnown 11 候有效,Server 会马上返回一个数据节段的信息 FF 当出现错误的时候返回信息 偏移 类型 Length(byte) 0 ErrCode 2 2 ErrMsg END FE 多段信息传输的结束 空Client 对 Server 提交数据的格式:偏移 区域 类型 Length(byte)0 HEAD Data Length 31 2 3 Compressed 14 DATA Command ID 15 Command Data Data Length - 1Command ID 与 Command Data 的说明:ID 类型 数据格式0 COM_SLEEP 1 COM_
11、QUIT NULL2 COM_INIT_DB Database name3 COM_QUERY stand query string4 COM_FIELD_LIST table name 128 wildcard1285 COM_CREATE_DB Database name6 COM_DROP_DB Database name7 COM_REFRESH options(bits)8 COM_SHUTDOWN NULL9 COM_STATISTICS NULL10 COM_PROCESS_INFO NULL11 COM_CONNECT 12 COM_PROCESS_KILL sid413 CO
12、M_DEBUG NULL14 COM_PING NULL15 COM_TIME 16 COM_DELAYED_INSERT 17 COM_CHANGE_USER userpasswddb18 COM_BINLOG_DUMP 19 COM_TABLE_DUMP 20 COM_CONNECT_OUT 第八节 Client 如何通过 Server 的用户认证协议分析完成了,我尝试着让它工作起来,可是认证这个部分遇到了麻烦,Mysql Server 在 Client 连接上它的时候,会首先返回给 Client 一个数据包,包含协议的版本号,版本信息,SessionID,一个 8字节的 Key,就是这个
13、 Key 的原因。 Client 会使用这个 Key 来加密密码,然后将用户名,密码,需要打开的数据库等信息发送给 Server,这样就完成认证了。我不知道 Client 是如何利用这个 Key 来加密的,所以我打算跳过密码,我将 Client 的数据包重组,去掉 Password 的信息之后,我成功了,但是集群里面的 Mysql 用户都是没有密码的,安全性多多少少有些问题,不过这些服务器都是放在 HA 后面的,没有外部的 IP 地址,应该问题不大,不过多多少少是个缺憾。但是我总要知道用户的密码是否正确吧?怎么办呢?使用一个专用的 Mysql 来完成密码认证。安装一个最小化资源的 Mysql
14、Server 用来做 MysqlAuth(专用认证服务器),当 Client 连接后,就将MysqlAuth 的第一个数据包返回给 Client,这里面当然就包含着 Key,然后 Client 会使用这个 Key,加密密码之后,将认证信息发回来,这个时候,MysqlHA 系统就会将这个信息转发给 MysqlAuth,并且自己保留一份,如果认证通过了,就把保留的那一份进行重组,去掉密码信息,然后用重组后的认证信息去连接集群中的服务器。第九节 系统的结构与流程回页首回页首图中 HA 就是使用 HeartBeat 方式建立的高可靠性系统(具体实现方法请参考 http:/www.linuxvirtua
15、lserver.org/)。Proxy 为 Mysql-Proxy 系统,MysqlAuth 是专用的认证服务器。红色的 RealServer 为主要服务器,可以进行数据更新操作,同时将数据同步到其它的RealServer。 下图描述的就是 Client 认证过程下图描述的是认证不通过以及认证通过后与 RealServer 建立联接的过程上图讲述了连接建立后,系统处理 SQL Query 请求的过程第十节 结束语我现在已经基本完成了 mysql-proxy 的程序的开发,但是目前仍然处于测试阶段,最新的版本是0.0.4,下一个版本仍然还在修订中。从 0.0.3 版本开始,mysql-proxy
16、 已经可以完整的跑完 mysql 自身提供的 sql-bench 了,但是这个 sql-bench 只能提供单点的性能,没有对集群的 mysql 系统提供测试功能。系统提供了动态采集 RealServer 上的 LoadAvg 然后反馈给 Mysql Proxy 的程序,但是由于这部分我没有进行测试,所以我在前面的测试中采用的请求分配方式是轮询方式,如果出现两个负载一样的RealServer 系统会自动的在它们之间轮换选择。Mysql-proxy 的源代码您可以到我的网站下载: http:/netsock.org/bbs/Mysql-HA-Cluster 项目。还有一部分测试的数据我也会在那里公布。 如何进行系统测试?既然是专门为 Linux+Apache+Php+Mysql 这样的系统做的集群,就应该找一个实际的应用来跑跑看,然后模拟大量的访问,来进行测试。选择一个论坛