开发者

MySQL做读写分离提高性能缓解数据库压力

目录
  • 一 什么是读写分离
  • 二 读写分离的好处
  • 三 读写分离提高性能之原因
  • 四 读写分离示意图
  • 五 读写分离模拟

一 什么是读写分离

虽然知道处理大数据量时,数据库为什么要做读写分离,原因很简单:读写分离是mysql优化的一方面,它可以提高性能,缓解数据库压力,缓解服务器压力。

MySQL Proxy最强大的一项功能是实现“读写分离(Read/Write Splitting)”。基本的原理是让主数据库处理事务性查询,而从数据库处理SELECT查询。

数据库复制被用来把事务性查询导致的变更同步到集群中 的从数据库。 当然,主服务器也可以提供查询服务。使用读写分离最大的作用无非是环境服务器压力。可以看下这张图:

MySQL做读写分离提高性能缓解数据库压力

二 读写分离的好处

1.增加冗余

2.增加了机器的处理能力

3.对于读操作为主的应用,使用读写分离是最好的场景,因为可以确保写的服务器压力更小,而读又可以接受点时间上的延迟。

三 读写分离提高性能之原因

1.物理服务器增加,负荷增加

2.主从只负责各自的写和读,极大程度的缓解X锁和S锁争用

3.从库可配置myisam引擎,提升查询性能以及节约系统开销

4.从库同步主库的数据和主库直接写还是有区别的,通过主库发送来的binlog恢复数据,但是,最重要区别在于主库向从库发送binlog是异步的,从库恢复数据也是异步的

5.读写分离适用与读远大于写的场景,如果只有一台服务器,当select很多时,update和delete会被这些select访问中的数据堵塞,等待select结束,并发性能不高。对于写和读比例相近的应用,应该部署双主相互复制

6.可以在从库启动是增加一些参数来提高其读的性能,例如--skip-innodb、--skip-bdb、--low-priority-updates以及--delay-key-write=ALL。当然这些设置也是需要根据具体业务需求来定得,不一定能用上

7.分摊读取。假如我们有1主3从,不考虑上述1中提到的从库单方面设置,假设现在1 分钟内有10编程客栈条写入,150条读取。那么,1主3从相当于共计40条写入,而读取总数没变,因此平均下来每台服务器承担了10条写入和50条读取(主库不 承担读取操作)。

因此,虽然写入没变,但是读取大大分摊了,提高了系统性能。另外,当读取被分摊后,又间接提高了写入的性能。所以,总体性能提高了,说白 了就是拿机器和带宽换性能。MySQL官方文档中有相关演算公式:官方文档 见6.9FAQ之“MySQL复制能够何时和多大程度提高系统性能”

8.MySQL复制另外一大功能是增加冗余,提高可用性,当一台数据库服务器宕机后能通过调整另外一台从库来以最快的速度恢复服务,因此不能光看性能,也就是说1主1从也是可以的。

四 读写分离示意图

MySQL做读写分离提高性能缓解数据库压力

五 读写分离模拟

实验环境简介

serv01:代理服务器 192.168.1.11 serv01.host.com

serv08:主服务器(主要写数据,可读可写) 192.168.1.18 serv08.host.com

serv09:从服务器(主要读数据) 192.168.1.19 serv09.host.com

操作系统版本

RHEL Server6.1 64位系统

使用到的软件包版本

mysql-5.5.29-linux2.6-x86_64.tar.gz

 mysql-proxy-0.8.2-linux-glibc2.3-x86-64bit.tar.gz

第一步,搭建MySQL服务器,清空日志。注意:代理服务器中不需要装MySQL

第二步,拷贝mysql-proxy-0.8.2-linux-glibc2.3-x86-64bit.tar.gz文件,解压文件

[root@larrywen 1005]# scp /opt/soft/ule-mysql/mysql-proxy-0.8.2-linux-glibc2.3-x86-64bit.tar.gz 192.168.1.11:/opt [root@serv01 opt]# tar -xvf mysql-proxy-0.8.2-linux-glibc2.3-x86-64bit.tar.gz -C /usr/local/ [root@serv01 opt]# cd /usr/local/ [root@serv01 local]# mv mysql-proxy-0.8.2-linux-glibc2.3-x86-64bit/ mysql-proxy [root@serv01 local]# ll mysql-proxy/ total 24 drwxr-xr-x. 2 7157 wheel 4096 Aug 17 2011 bin drwxr-xr-x. 2 7157 wheel 4096 Aug 17 2011 include drwxr-xr-x. 4 7157 wheel 4096 Aug 17 2011 libphp drwxr-xr-x. 2 7157 wheel 4096 Aug 17 2011 libexec drwxr-xr-x. 3 7157 wheel 4096 Aug 17 2011 licenses drwxr-xr-x. 3 7157 wheel 4096 Aug 17 2011 share --可以查看帮助 [root@serv01 bin]# ./mysql-proxy --help-all 

第三步,serv08主服务器创建用户,serv09从服务器创建用户,注意用户名和密码一致

serv08mysql>grantallon*.*to'larry'@'192.168.1.%'identifiedby'larry';QueryOK,0rowsaffected(0.00sec)serv09mysql>grantallon*.*to'larry'@'192.168.1.%'identifiedby'larry';QueryOK,0rowsaffected(0.00sec)

第四步,serv09从服务器更改设置,开启slave,查看slave状态。创建测试数据库,插入测试数据

serv09mysql>changemastertomaster_host='192.168.1.18',master_user='larry',master_password='larry',master_port=3306,master_log_file='mysql-bin.000001',master_log_pos=107;
QueryOK,0rowsaffected(0.01sec)
mysql>startslave;
QueryOK,0rowsaffected(0.00sec)
mysql>showslavestatus\G;***************************1.row***************************Slave_IO_State:WaitingformastertosendeventMaster_Host:192.168.1.18Master_User:larryMaster_Port:3306Connect_Retry:60Master_Log_File:mysql-bin.000001Read_Master_Log_Pos:107Relay_Log_File:serv09-relay-bin.000002Relay_Log_Pos:253Relay_Master_Log_File:mysql-bin.000001Slave_IO_Running:YesSlave_SQL_Running:YesReplicate_Do_DB:Replicate_Ignore_DB:Replicate_Do_Table:Replicate_Ignore_Table:Replicate_Wild_Do_Table:Replicate_Wild_Ignore_Table:Last_Errno:0Last_Error:Skip_Counter:0Exec_Master_Log_Pos:107Relay_Log_Space:410Until_Condition:NoneUntil_Log_File:Until_Log_Pos:0Master_SSL_Allowed:NoMaster_SSL_CA_File:Master_SSL_CA_Path:Master_SSL_Cert:Master_SSL_Cipher:Master_SSL_Key:Seconds_Behind_Master:0Master_SSL_Verify_Server_Cert:NoLast_IO_Errno:0Last_IO_Error:Last_SQL_Errno:0Last_SQL_Error:Replicate_Ignore_Server_Ids:Master_Server_Id:21rowinset(0.00sec)ERROR:Noqueryspecifiedmysql>selectuser,password,hostfrommysql.user;+------+-------------------------------------------+-----------------+|user|password|host|+------+-------------------------------------------+-----------------+|root||localhost||root||serv08.host.com||root||127.0.0.1||root||::1||||localhost||||serv08.host.com||rep|*0CDC8D34246E22649D647DB04E7CCCACAB4368B6|192.168.1.%|+------+-------------------------------------------+-----------------+7rowsinset(0.00sec)
mysql>createdatabaselarrydb;
QueryOK,1rowaffected(0.00sec)
mysql>uselarrydb;Databasechanged
mysql>createtableuser(idint,namevarchar(30));
QueryOK,0rowsaffected(0.01sec)
mysql>insertintouservalues(1,'larrywen');
QueryOK,1rowaffected(0.01sec)
mysql>insertintouservalues(2,'wentasy');
QueryOK,1rowaffected(0.00sec)
mysql>select*fromuser;+------+----------+|id|name|+------+----------+|1|larrywen||2|wentasy|+------+----------+2rowsinset(0.00sec)serv09mysql>select*fromlarrydb.user;+------+----------+|id|name|+---php---+----------+|1|larrywen||2|wentasy|+------+----------+2rowsinset(0.00sec)

第五步,为了查看现象,serv09从服务器关闭slave

mysql>stopslave;
QueryOK,0rowsaffected(0.01sec)

第六步,serv 01查看是否有MySQL用户,修改rw-splitting.Lua文件,修改如下几个参数

[root@serv01mysql-proxy]#idmysqluid=500(mysql)gid=500(mysql)groups=500(mysql)[root@serv01mysql-proxy]#vimrw-splitting.lua
[root@serv01mysql-proxy]#catrw-splitting.lua|grep-emin_idle_connections-emax_idle_connections-eis_debugmin_idle_connections=1,--最小空闲连接数,为了测试,这里设置为1max_idle_connections=1,--最大空闲连接数,为了测试,这里设置为1
is_debug=true--是否打开Debug调试,为了查看调试信息,这里设置为true

第七步,启动mysql-proxy

[root@serv01mysql-proxy]#/etc/init.d/mysql-proxystartStartingmysql-proxy:--先确定是否可以连接
[root@serv01~]#mysql-ularry-plarry-h192.168.1.18WelcometotheMySQLmonitor.Commandsendwith;or\g.YourMySQLconnectionidis6Serverversion:5.5.29-logSourcedistributionCopyright(c)2000,2012,oracleand/oritsaffiliates.Allrightsreserved.OracleisaregisteredtrademarkofOracleCorp编程客栈orationand/oritsaffiliates.Othernamesmaybetrademarksoftheirrespectiveowners.Typ编程客栈e'help;'or'\h'forhelp.Type'\c'toclearthecurrentinputstatement.
mysql>exitBye
[root@serv01~]#mysql-ularry-plarry-h192.168.1.19WelcometotheMySQLmonitor.Commandsendwith;or\g.YourMySQLconnectionidis8Serverversion:5.5.29-logSourcedistributionCopyright(c)2000,2012,Oracleand/oritsaffiliates.Allrightsreserved.OracleisaregisteredtrademarkofOracleCorporationand/oritsaffiliates.Othernamesmaybetrademarksoftheirrespectiveowners.Type'help;'or'\h'forhelp.Type'\c'toclearthecurrentinputstatement.
mysql>exitBye

第八步,查看现象

[root@serv01~]#/etc/init.d/mysql-proxystartStartingmysql-proxy:
[root@serv01~]#mysql-ularry-plarry-h192.168.1.11[connect_server]192.168.1.11:51054[1].connected_clients=0[1].pool.cur_idle=0[1].pool.max_idle=1[1].pool.min_idle=1[1].type=1[1].state=0[1]idle-connsbelowmin-idleWelcometotheMySQLmonitor.Commandsendwith;or\g.[read_query]192.168.1.11:51054currentbackend=0clientdefaultdb=clientusername=larryquery=select@@version_commentlimit1sendingtobackend:192.168.1.19:3306is_slave:falseserverdefaultdb:serverusername:larryin_trans:falsein_calc_found:falseCOM_QUERY:trueYourMySQLconnectionidis10Serverversion:5.5.29-logSourcedistributionCopyright(c)2000,2012,Oracleand/oritsaffiliates.Allrightsreserved.OracleisaregisteredtrademarkofOracleCorporationand/oritsaffiliates.Othernamesmaybetrademarksoftheirrespectiveowners.Type'help;'or'\h'forhelp.Type'\c'toclearthecurrentinputstatement.
mysql>
mysql>uselarrydb;[read_query]192.168.1.11:51054currentbackend=0clientdefaultdb=clientusername=larryquery=SELECTDATABASE()sendingtobackend:192.168.1.19:3306is_slave:falseserverdefaultdb:serverusername:larryin_trans:falsein_calc_found:falseCOM_QUERY:true[read_query]192.168.1.11:51054currentbackend=0clientdefaultdb=clientusername=larrysendingtobackend:192.168.1.19:3306is_slave:falseserverdefaultdb:serverusername:larryin_trans:falsein_calc_found:falseCOM_QUERY:falseDatabasechanged
mysql>select*fromuser;
[read_query]192.168.1.11:51054currentbackend=0clientdefaultdb=larrydbclientusername=larryquery=select*fromusersendingtobackend:192.168.1.19:3306is_slave:falseserverdefaultdb:larrydbserverusername:larryin_t开发者_oraclerans:falsein_calc_found:falseCOM_QUERY:true
+------+----------+
|id|name|+------+----------+
|1|larrywen|
|2|wentasy|
+------+----------+
2rowsinset(0.00sec)
mysql>insertintouservalues(3,'jsutdb');
[read_query]192.168.1.11:51644currentbackend=0clientdefaultdb=larrydbclientusername=larryquery=insertintouservalues(3,'jsutdb')sendingtobackend:192.168.1.19:3306is_slave:falseserverdefaultdb:larrydbserverusername:larryin_trans:falsein_calc_found:falseCOM_QUERY:true
QueryOK,1rowaffected(0.00sec)serv08
mysql>select*fromuser;
+------+----------+|id|name|
+------+----------+|1|larrywen|
|2|wentasy|+------+----------+
2rowsinset(0.00sec)serv09
mysql>select*fromlarrydb.user;
+------+----------+|id|name|
+------+----------+|1|larrywen|
|2|wentasy|
|3|jsutdb|
+------+----------+
3rowsinset(0.00sec)

第九步,以上的测试虽有效果,但不是预期。排查原因,重新配置。发现proxy-read-only-backend-addresses和proxy-backend-addresses参数配置出错,proxy-read-only-backend-addresses应该配置成从服务器的IP地址,proxy-backend-addresses应该配置成主服务器的IP地址。

[root@serv01~]#vim/etc/init.d/mysql-proxy
[root@serv01~]#cat/etc/init.d/mysql-proxy#!/bin/sh##mysql-proxyThisscriptstartsandstopsthemysql-proxydaemon##chkconfig:-7830#processname:mysql-proxy#description:mysql-proxyisaproxydaemontomysql#Sourcefunctionlibrary../etc/rc.d/init.d/functions#PROXY_PATH=/usr/local/binPROXY_PATH=/usr/local/mysql-proxy/binprog="mysql-proxy"#Sourcenetworkingconfiguration../etc/sysconfig/network#Checkthatnetworkingisup.[${NETWORKING}="no"]&&exit0#Setdefaultmysql-proxyconfiguration.#PROXY_OPTIONS="--daemon"PROXY_OPTIONS="--proxy-read-only-backend-addresses=192.168.1.19:3306--proxy-backend-addresses=192.168.1.18:3306--proxy-lua-script=/usr/local/mysql-proxy/share/doc/mysql-proxy/rw-splitting.lua"#PROXY_PID=/usr/local/mysql-proxy/run/mysql-proxy.pidPROXY_PID=/var/run/mysql-proxy.pid#Sourcemysql-proxyconfiguration.if[-f/etc/sysconfig/mysql-proxy];then./etc/sysconfig/mysql-proxyfiPATH=$PATH:/usr/bin:/usr/local/bin:$PROXY_PATH#Bydefaultit'sallgoodRETVAL=0#Seehowwewerecalled.case"$1"instart)#Startdaemon.echo-n$"Starting$prog:"$NICELEVEL$PROXY_PATH/mysql-proxy$PROXY_OPTIONS--daemon--pid-file=$PROXY_PID--user=mysql--log-level=debug--log-file=/var/log/mysql-proxy.log--proxy-address=192.168.1.11:3306RETVAL=$?echoif[$RETVAL=0];thentouch/var/lock/subsys/mysql-proxyfi;;stop)#Stopdaemons.echo-n$"Stopping$prog:"killproc$progRETVAL=$?echoif[$RETVAL=0];thenrm-f/var/lock/subsys/mysql-proxyrm-f$PROXY_PIDfi;;restart)$0stopsleep3$0start;;condrestart)[-e/var/lock/subsys/mysql-proxy]&&$0restart;;status)statusmysql-proxyRETVAL=$?;;*)echo"Usage:$0{start|stop|restart|status|condrestart}"RETVAL=1;;esacexit$RETVAL

第十步,测试。插入数据,可以发现连接的是主服务器,查询的时候也是主服务器。说明主服务器和从服务器均有读的的功能。

[root@serv01~]#mysql-ularry-plarry-h192.168.1.11[connect_server]192.168.1.11:57891[1].connected_clients=0[1].pool.cur_idle=0[1].pool.max_idle=1[1].pool.min_idle=1[1].type=1[1].state=1[1]idle-connsbelowmin-idle[read_query]192.168.1.11:57891currentbackend=0clientdefaultdb=clientusername=larryquery=select@@version_commentlimit1sendingtobackend:192.168.1.18:3306is_slave:falseserverdefaultdb:serverusername:larryin_trans:falsein_calc_found:falseCOM_QUERY:true
mysql>insertintouservalues(5,'test');
QueryOK,
1rowaffected(0.01sec)
[read_query]192.168.1.11:57893currentbackend=0clientdefaultdb=larrydbclientusername=larryquery=insertintouservalues(5,'test')sendingtobackend:192.168.1.18:3306is_slave:falseserverdefaultdb:larrydbserverusername:larryin_trans:falsein_calc_found:falseCOM_QUERY:true
mysql>select*fromuser;
+------+----------+|id|name|
+------+----------+|1|larrywen|
|2|wentasy|
|5|test|+------+----------+
3rowsinset(0.00sec)
[read_query]192.168.1.11:57893currentbackend=0clientdefaultdb=larrydbclientusername=larryquery=select*fromusersendingtobackend:192.168.1.18:3306is_slave:falseserverdefaultdb:larrydbserverusername:larryin_trans:falsein_calc_found:falseCOM_QUERY:trueserv08主服务器查看数据,可以查询到,说明主服务器可以写mysql>select*fromlarrydb.user;
+------+----------+|id|name|
+------+----------+|1|larrywen|
|2|wentasy|
|5|test|+------+----------+
3rowsinset(0.00sec)
serv09从服务器查询数据,发现不可查询到,说明从服务器只读
mysql>
mysql>select*fromlarrydb.user;
+------+----------+|id|name|
+------+----------+|1|larrywen|
|2|wentasy|
|3|jsutdb|
|4|db|+------+----------+
4rowsinset(0.00sec)

第十一步,开启slave。发现数据同步成功。

mysql>startslave;
QueryOK,0rowsaffected(0.00sec)
mysql>select*fromlarrydb.user;
+------+----------+
|id|name|
+------+----------+
|1|larrywen|
|2|wentasy|
|3|jsutdb|
|4|db|
|5|test|
+------+----------+
5rowsinset(0.00sec)

以上就是MySQL做读写分离提高性能缓解数据库压力的详细内容,更多关于MySQL缓解数据库压力的资料请关注我们其它相关文章!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新数据库

数据库排行榜