数据库优化之读写分离

来源:互联网 发布:淘宝买家秀福利木耳 编辑:程序博客网 时间:2024/04/30 02:12

前言
网站发展的初期,由于没有太多访问量,一般来讲只需要一台服务器就够了,这时候应用软件、数据库、文件等所有资源都在一台服务器上。随着用户量和数据文件的增加,单台服务器的性能达到瓶颈,这时候需要把应用软件、数据库和文件资源单独拆分出来,满足他们对服务器硬件资源的不同需求。比如应用软件更多的需要CPU,数据库对磁盘读写多,需要快速的磁盘和充足的内存。随着业务量的再次增加,这时候需要搭建服务器集群来缓解压力,提升网站的性能,应用服务器通过软件或硬件的方式来实现负载均衡,以此来改善负载压力。数据库服务器则从单台到多台,利用主从,读写分离缓存等技术来打破数据瓶颈。
全文数据库默认为mysql


一 优化思路及过程
数据库的优化顺序要根据网站场景具体分析,通常为以下优化过程
1、服务器配置优化
1)服务器硬件升级是所有优化方案的前提,一般来讲SQL本身的执行速度都不会太慢,慢主要是需要从磁盘把结果集读入到内存,比如改动大表时Copying to tmp table on disk这种状态常常占据很大比例时间。所以对于单个数据库,优化的次序一般是RAM、高速硬盘、CPU能力。
2)大多网站的MySQL是IO密集型的,如果你的MySQL是个CPU密集型的话,那么很可能你的MySQL参数配置需要优化了。针对mysql不同的引擎参数配置优化也有所不同
INNODB表的优化
innodb_buffer_pool_size
主要存放热数据,按照page来存放,page为最小单位,甚至是按段来存放
建议值: 如果是专用数据库server 建议分到物理内存的50% -- 75% 
max_heap_table_size,tmp_table_size
此变量定义了用户可以创建的内存表(memory table)的大小.如果内存临时表超出了限制,MySQL就会自动地把它转化为基于磁盘的表,存储在指定的tmpdir目录下。tmp_table_size 和 max_heap_table_size 大小要一致
innodb_flush_log_at_trx_commit
如果在导数据,可能是2天或者3天也没有导完,那么可能是这个参数设置为1的结果导致
1  为每一次事务进一次刷新到磁盘,安全度高,但是性能最低,经常会导致导数据最慢
0  每秒钟进一下事务的刷新到磁盘
2  一般建议值,大约每秒一次事务的刷新及同步到磁盘,实际只写到操作系统的buffer中,操作系统如果断电会导致失误丢失;#因为导数据都是人为参与的过程所以设置为2,让速度最大化完成,如果出错再手动搞一次即可。
MYISAM表的优化:
key_buffer_size
key_buffer_size指定索引缓冲区的大小,它决定索引处理的速度,尤其是索引读的速度。key_buffer_size是对MyISAM表性能影响最大的一个参数,通过检查状态值Key_read_requests和Key_reads,可以知道key_buffer_size设置是否合理。比例key_reads /key_read_requests应该尽可能的低,至少是1:100,1:1000更好

2、sql和索引的优化
开启mysql的慢查询,查询是否是某个SQL语句占用过多资源,如果是的话,可以对SQL语句进行优化,比如优化 insert 语句、优化 group by 语句、优化 order by 语句、优化 join 语句等等。

3、缓存技术
搭建redis或者memcache做为缓存层,提高数据库读取速度。

4、主从备份读写分离
读写分离既可以通过代码程序实现,也能利用第三方工具做,提高系统负载能力。

5、数据的垂直拆分
垂直拆分,其实就是根据你模块的耦合度,将一个大的系统分为多个小的系统,也就是分布式系统。

6、数据的水平拆分
将某个访问极其频繁的表再按照某个字段的某种规则来分散到多个表之中,每个表中包含一部分数据。

以上就是大多情况下数据库的优化顺序,读写分离是数据库优化的必经之路,所以在这里我们了解一下读写分离的功能、使用场景和一些配置。

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

*读写分离的好处*
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的高可用负载集群。读写分离只是负载了读写的压力,如果想再次提升数据库的性能就要进行数据垂直和水平拆分的操作了。










0 0
原创粉丝点击