mysql读写分离

Mysql读写分离

首先我们必须知道为什么要分离。这个一般是由于以下原因导致的。

  1. 性能,单台数据库实在是撑不住了
  2. HA,防止单台数据库挂掉造成应用不可用
  3. 扩展,由于业务新增了新的需求

以上几种是我们常见的要进行分离的原因。其中做多的可能是第一和第二种。这个主要还是涉及到钱和服务器的数量上。一般业务都会在前端部署更多的服务器,而在最后端的数据库服务器往往比较少。但是对于好多web2.0 UGC这样的业务的网站还是有必要重视后端的速度和稳定性。   分离的多种方案

  1. query proxy,这个一般是由单独的服务器来进行的,由它负责这个sql语句路由到哪个服务器上。这种proxy的话最好还是要建立HA方式,不然这个proxy就是一个单点故障。这个在之前人人的系统中就是如此,虽然只是负责发起查询的时候建立真实mysql服务器和应用服务器连接,但是还是比较危险的。
  2. Load balance, 后面一堆服务器,通过轮寻的方式来访问mysql服务器。这个很多时候是通过内部DNS来实现。

  分离的多个原则

  1. 根据内容进行分离,针对某个表或者某个库的查询到哪个服务器上。这个其实就是数据库分区的概念。这个在之前的人人系统中我们也经历过从单台数据库服务器,最终分离出所有的应用到单独的数据库中,并且都有了单独的服务器。这样一旦服务器出现问题,也只会影响到单独的应用,而不会是全部的应用都不可用。
  2. 根据后端mysql服务器的状态,当第一台服务器到达某个标准状态时候再请求到第二台服务器上。这种原则容易造成第一台服务器长时间的高负载运行。
  3. 根据session分离,根据session和后端服务器的映射表来分离。这个对于proxy的要求比较高,需要在内部存储这样一个映射表,并且要可以实时进行更新映射表。

  现有的问题

  1. 有多个写,这个现在有双MASTER的方案。多个分区的也会总有一个master实在忙不过来的时候,特别是web2.0网站的UGC内容。对于cms系统来说完全没有必要。
  2. 没有session隔离,这个有可能导致查询到的数据不准确。这个就是如何保证用户刚提交内容后马上看到提交后的结果。这个之前在人人某个网页游戏中发生过类似事情,在程序中update数据后立刻去读数据库。但是实际上是update到master数据库,但是select查询的是slave数据库。后面我说到seconds_behind_master这个时间并不准就是这里,虽然seconds_behind_master=0但是还是不能在master做了update后可以实时的传导到slave上啊。
  3. 需要用到内部DNS,或者hosts文件来进行调度。

  这种分离导致的问题

  1. 导致问题的复杂,一个简单的update语句会导致所有的相关数据库服务器进行update。
  2. 导致过多的读写,slave方案的最大问题就是在master服务器上的写同样会传导到slave服务器上,同时slave服务器还要支持读。

  现在我们在mysql5.1以上的版本中使用行复制,但是这个现在还不是很成熟。 不要相信show slave statusG;中的seconds_behind_master,这个在实际中并不太准确。   之前我用到的几种query proxy。

  1. 一种是比较山寨的方法,让程序员在在代码中嵌入,insert, update这种语句直接连接master服务器,而select直接连接到slave服务器。在多个slave服务器之前使用haproxy进行调度代理。这种方法的缺点是,当业务调整,或者服务器IP更改后还要去修改DNS服务器去,同时还得寄希望于程序中没有把insert这种语句没有一个指向slave服务器上。当然优点就是部署简单。
  2. mysql proxy: 这个貌似很官方的,但是配置语法较麻烦,容易弄错,自己没有实践过,周边同事实践后感觉不好。
  3. 最后一种是人人正在使用的。是完全自己做的,用的是ICE框架。直接一个单独的配置文件进行配置就可。配置文件的主要内容是instance名字,数据库名,数据库IP地址,读还是写,还是读写都可。这个东西使用方式对于程序员来说很简单,它只要知道连接哪个数据库用什么instance名字就可,不需要知道其他任何信息。其它信息(读写方式,数据库地址等等)都是靠这个中间层来确定的。同时对于这些信息都会缓存在应用程序本地,以后不用再次请求中间层,而是直接连接对应的数据库就可以了。第一次应用程序请求的时候会请求到中间层,中间层返回对应的数据库地址和名字以及数据库的用户名密码等信息,然后应用程序使用这些信息来连接数据库,而第二次请求的时候就直接连接数据库了。但是这个系统的问题是每个应用程序本地都要知道这个中间层的地址,每次修改中间层的配置文件后都要重新reload下通知所有应用程序下次请求都要先请求下中间层,无论修改的配置跟你这个应用程序有没有关系。

###########################################

Best regards Timo Seven