数据库读写分离

二 读写分离概述
读写分离从字面意思就可以理解,就是把对数据库的读操作和写操作分离开。读写分离在网站发展初期可以一定程度上缓解读写并发时产生锁的问题,将读写压力分担到多台服务器上,通常用于读远大于写的场景。

*读写分离的好处*
1)数据是网站的生命,读写分离通过主从备份数据,保证了系统的冗余,保护了珍贵的数据。
2)提高了系统性能,一定程度提高了数据库负载能力。

*适用读写分离场景*
1)网站初期想要缓解数据负载最简单可行的方案。
2)服务器面对的是读远大于写的场景,并且业务能够允许时间上一些延迟。

*读写分离实现方式*
目前读写分离方案网上找了几个并做了对比。
1.mycat 基于阿里的cobar改版的(比较稳定,论坛活跃)
2.atlas 360开发的 网友说不是很稳定 (已经很久没更新)
3.mysql-proxy mysql自带 (不是很稳定)
4.oneproxy 比较稳定 性能也很好 (需要付费)
5.amoeba 好像还行,有一些公司使用 (但是很久没有更新了)

三 mycat读写分离配置
综上所述,我选择用mycat来实现mysql的读写分离。
 
上图的设计思路是这样的
1.当master正常时,读操作发生在两个slave上,写操作发生在master上。master通过主从配置实时同步数据到两个slave上。
2.当master挂了,为了数据的一致性,和master为主从关系的slave2被停止访问。这时slave1负责读和写,当master重新恢复后,slave1同步数据给master,然后再次恢复最初读写状态。


 
为了实现上述思路,我们需要配置mysql的主从备份和主主备份,这个很简单,这里就不叙述了。
Mycat的前期工作需要 Java 环境,ubuntu下直接apt-get就可以下载,网上教程很多,下载好java之后再配置一下jdk环境变量
Whereis  jvm  查看jvm路径
然后 vi /etc/profile
export JAVA_HOME=/usr/lib/jvm/java-1.7.0-openjdk-amd64  
export CLASSPATH=.:$JAVA_HOME/lib:$JAVA_HOME/jre/lib:$CLASSPATH  
export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH  
 
接着 source /etc/profile 使配置生效
配置好jdk环境变量后就可以下载mycat了
在mycat 官网就可以下载各种版本,我下载的是 Mycat-server-1.5-release版本
 
Mycat的配置文件主要是conf下的schema.xml,rule.xml,server.xml。
 
我只是简单的配置了mysql的读写分离,分片分库这些功能并没有使用,所以我只配置了schema.xml和server.xml这两个文件
 
Server.xml 文件是mycat的登录信息,我修改了以下配置
 <user name="test">   mycat登录用户名
                <property name="password">test</property>mycat登录密码  
                <property name="schemas">test,test1 (有多个 数据库 可以添加多个逻辑库) </property>  
        </user>                                           
                                                                                                                                               
        <user name="user">
                <property name="password">user</property>
                <property name="schemas">test</property>
                <property name="readOnly">true</property>
        </user>
 
 
Schema.xml 文件里有mycat分库分片和读写分离的配置
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://org.opencloudb/" >
 
        <schema name=" test " checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">     这里的test名字要和server里的一致
       <schema name="test1" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn2">
     
        <dataNode name="dn1" dataHost="localhost1" database="test" />
        <dataNode name="dn2" dataHost="localhost1" database="test1" />
     
        <dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"
                writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
               
                <writeHost host="hostM1" url="localhost:3306" user="root"
                        password="">
                   </writeHost>
                <writeHost host="hostS1" url="192.168.1.1:3306" user="root"
                        password="" />
              
        </dataHost>
        
</mycat:schema>
 
 这里我把注释文件全都删除了,因为我只需要实现读写分离,所以配置比较简单。
 这里需要注意的是 balance, switchType, writeType

balance="0", 不开启读写分离机制,所有读操作都发送到当前可用的writeHost上。
balance="1",全部的readHost与stand by writeHost参与select语句的负载均衡,简单的说,当双主双从模式(M1->S1,M2->S2,并且M1与M2互为主备),正常情况下,M2,S1,S2都参与select语句的负载均衡。
balance="2",所有读操作都随机的在writeHost、readhost上分发。
balance="3",所有读请求随机的分发到wiriterHost对应的readhost执行,writerHost不负担读压力
writeType表示写模式
writeType="0",所有的操作发送到配置的第一个writehost
writeType="1",随机发送到配置的所有writehost
writeType="2",不执行写操作
switchType指的是切换的模式,目前的取值也有4种:
switchType=‘-1‘ 表示不自动切换
switchType=‘1‘ 默认值,表示自动切换
switchType=‘2‘ 基于MySQL主从同步的状态决定是否切换,心跳语句为show slave status
switchType=‘3‘基于MySQL galary cluster的切换机制(适合集群)(1.4.1),心跳语句为show status like ‘wsrep%‘。
我上面的配置是实现的两个mysql都参与读操作,写操作只在hostm上进行,当hostm挂掉之后在hosts上进行。
 
完成后进入bin文件,./mycat start 启动mycat
 
如果只是实现读写分离,mycat的配置文件还是比较简单的,不过有几点需要注意。
 
1)确定上面mysql用户是否有远程登录的权限
2)mycat有两个端口,一个是8066,一个是9066,其中9066是管理端口,8066是数据端口,我之前一直登录管理端口,show  tables;时不能成功执行,后来才发现登录8066才行。

遇到的问题和总结
1)在优化的过程中,通过给予合适的mysql参数配置解决了数据库cpu密集,假死的问题。
2)mycat读写分离架构中读数据库使用myisam引擎,然而myisam引擎面对长查询和复杂查询不能体现出优越的查询速度。所以使用myisam引擎作为读服务器还有待继续考虑。
3)至此,mycat读写分离就配置完成了,不过以上的架构还有一个mycat单点问题,可以通过LVS+Keepalived搭建MYCAT的高可用负载集群。读写分离只是负载了读写的压力,如果想再次提升数据库的性能就要进行数据垂直和水平拆分的操作了。