构建高性能web之路------mysql读写分离实战

一个完整的mysql读写分离环境包括以下几个部分:

  • 应用程序client
  • database proxy
  • database集群

在本次实战中,应用程序client基于c3p0连接后端的database proxy。database proxy负责管理client实际访问database的路由策略,采用开源框架amoeba。database集群采用mysql的master-slave的replication方案。整个环境的结构图如下所示:

实战步骤与详解

一.搭建mysql的master-slave环境

1)分别在host1(10.20.147.110)和host2(10.20.147.111)上安装mysql(5.0.45),具体安装方法可见官方文档

2)配置master

首先编辑/etc/my.cnf,添加以下配置:

log-bin=mysql-bin #slave会基于此log-bin来做replication
server-id=1
#master的标示
binlog-do-db = amoeba_study #用于master-slave的具体数据库

然后添加专门用于replication的用户:

mysql> GRANT REPLICATION SLAVE ON *.* TO [email protected] IDENTIFIED BY
‘111111‘;

重启mysql,使得配置生效:

/etc/init.d/mysqld restart

最后查看master状态:

3)配置slave

首先编辑/etc/my.cnf,添加以下配置:

server-id=2 #slave的标示

配置生效后,配置与master的连接:

mysql> CHANGE MASTER TO
    -> MASTER_HOST=‘10.20.147.110‘,
  
 -> MASTER_USER=‘repl‘,
    -> MASTER_PASSWORD=‘111111‘,
    ->
MASTER_LOG_FILE=‘mysql-bin.000003‘,
    -> MASTER_LOG_POS=161261;

其中MASTER_HOST是master机的ip,MASTER_USER和MASTER_PASSWORD就是我们刚才在master上添加的用户,MASTER_LOG_FILE和MASTER_LOG_POS对应与master
status里的信息

最后启动slave:

mysql> start slave;

4)验证master-slave搭建生效

通过查看slave机的log(/var/log/mysqld.log):

100703 10:51:42 [Note] Slave I/O thread: connected to master
‘[email protected]:3306‘,  replication started in log ‘mysql-bin.000003‘ at
position 161261

如看到以上信息则证明搭建成功,如果有问题也可通过此log找原因

二.搭建database proxy

此次实战中database proxy采用amoeba
,它的相关信息可以查阅官方文档,不在此详述

1)安装amoeba

下载amoeba(1.2.0-GA)后解压到本地(D:/openSource/amoeba-mysql-1.2.0-GA),即完成安装

2)配置amoeba

先配置proxy连接和与各后端mysql服务器连接信息(D:/openSource/amoeba-mysql-1.2.0-GA/conf/amoeba.xml):

[xhtml] view
plain
copyprint?

  1. <server>
  2. <!-- proxy server绑定的端口 -->
  3. <property name="port">8066</property>
  4. <!-- proxy server绑定的IP -->
  5. <!--
  6. <property name="ipAddress">127.0.0.1</property>
  7. -->
  8. <!-- proxy server net IO Read thread size -->
  9. <property name="readThreadPoolSize">20</property>
  10. <!-- proxy server client process thread size -->
  11. <property name="clientSideThreadPoolSize">30</property>
  12. <!-- mysql server data packet process thread size -->
  13. <property name="serverSideThreadPoolSize">30</property>
  14. <!-- socket Send and receive BufferSize(unit:K)  -->
  15. <property name="netBufferSize">128</property>
  16. <!-- Enable/disable TCP_NODELAY (disable/enable Nagle‘s algorithm). -->
  17. <property name="tcpNoDelay">true</property>
  18. <!-- 对外验证的用户名 -->
  19. <property name="user">root</property>
  20. <!-- 对外验证的密码 -->
  21. <property name="password">root</property>
  22. </server>

<server>
<!-- proxy server绑定的端口 -->
<property name="port">8066</property>

<!-- proxy server绑定的IP -->
<!--
<property name="ipAddress">127.0.0.1</property>
-->
<!-- proxy server net IO Read thread size -->
<property name="readThreadPoolSize">20</property>

<!-- proxy server client process thread size -->
<property name="clientSideThreadPoolSize">30</property>

<!-- mysql server data packet process thread size -->
<property name="serverSideThreadPoolSize">30</property>

<!-- socket Send and receive BufferSize(unit:K) -->
<property name="netBufferSize">128</property>

<!-- Enable/disable TCP_NODELAY (disable/enable Nagle‘s algorithm). -->
<property name="tcpNoDelay">true</property>

<!-- 对外验证的用户名 -->
<property name="user">root</property>

<!-- 对外验证的密码 -->
<property name="password">root</property>
</server>

以上是proxy提供给client的连接配置

[xhtml] view plaincopyprint?

  1. <dbServerList>
  2. <dbServer name="server1">
  3. <!-- PoolableObjectFactory实现类 -->
  4. <factoryConfig class="com.meidusa.amoeba.mysql.net.MysqlServerConnectionFactory">
  5. <property name="manager">defaultManager</property>
  6. <!-- 真实mysql数据库端口 -->
  7. <property name="port">3306</property>
  8. <!-- 真实mysql数据库IP -->
  9. <property name="ipAddress">10.20.147.110</property>
  10. <property name="schema">amoeba_study</property>
  11. <!-- 用于登陆mysql的用户名 -->
  12. <property name="user">root</property>
  13. <!-- 用于登陆mysql的密码 -->
  14. <property name="password"></property>
  15. </factoryConfig>
  16. <!-- ObjectPool实现类 -->
  17. <poolConfig class="com.meidusa.amoeba.net.poolable.PoolableObjectPool">
  18. <property name="maxActive">200</property>
  19. <property name="maxIdle">200</property>
  20. <property name="minIdle">10</property>
  21. <property name="minEvictableIdleTimeMillis">600000</property>
  22. <property name="timeBetweenEvictionRunsMillis">600000</property>
  23. <property name="testOnBorrow">true</property>
  24. <property name="testWhileIdle">true</property>
  25. </poolConfig>
  26. </dbServer>
  27. <dbServer name="server2">
  28. <!-- PoolableObjectFactory实现类 -->
  29. <factoryConfig class="com.meidusa.amoeba.mysql.net.MysqlServerConnectionFactory">
  30. <property name="manager">defaultManager</property>
  31. <!-- 真实mysql数据库端口 -->
  32. <property name="port">3306</property>
  33. <!-- 真实mysql数据库IP -->
  34. <property name="ipAddress">10.20.147.111</property>
  35. <property name="schema">amoeba_study</property>
  36. <!-- 用于登陆mysql的用户名 -->
  37. <property name="user">root</property>
  38. <!-- 用于登陆mysql的密码 -->
  39. <property name="password"></property>
  40. </factoryConfig>
  41. <!-- ObjectPool实现类 -->
  42. <poolConfig class="com.meidusa.amoeba.net.poolable.PoolableObjectPool">
  43. <property name="maxActive">200</property>
  44. <property name="maxIdle">200</property>
  45. <property name="minIdle">10</property>
  46. <property name="minEvictableIdleTimeMillis">600000</property>
  47. <property name="timeBetweenEvictionRunsMillis">600000</property>
  48. <property name="testOnBorrow">true</property>
  49. <property name="testWhileIdle">true</property>
  50. </poolConfig>
  51. </dbServer>
  52. </dbServerList>

<dbServerList>
<dbServer name="server1">
<!-- PoolableObjectFactory实现类 -->
<factoryConfig class="com.meidusa.amoeba.mysql.net.MysqlServerConnectionFactory">
<property name="manager">defaultManager</property>

<!-- 真实mysql数据库端口 -->
<property name="port">3306</property>

<!-- 真实mysql数据库IP -->
<property name="ipAddress">10.20.147.110</property>
<property name="schema">amoeba_study</property>

<!-- 用于登陆mysql的用户名 -->
<property name="user">root</property>

<!-- 用于登陆mysql的密码 -->
<property name="password"></property>

</factoryConfig>

<!-- ObjectPool实现类 -->
<poolConfig class="com.meidusa.amoeba.net.poolable.PoolableObjectPool">
<property name="maxActive">200</property>
<property name="maxIdle">200</property>
<property name="minIdle">10</property>
<property name="minEvictableIdleTimeMillis">600000</property>
<property name="timeBetweenEvictionRunsMillis">600000</property>
<property name="testOnBorrow">true</property>
<property name="testWhileIdle">true</property>
</poolConfig>
</dbServer>
<dbServer name="server2">

<!-- PoolableObjectFactory实现类 -->
<factoryConfig class="com.meidusa.amoeba.mysql.net.MysqlServerConnectionFactory">
<property name="manager">defaultManager</property>

<!-- 真实mysql数据库端口 -->
<property name="port">3306</property>

<!-- 真实mysql数据库IP -->
<property name="ipAddress">10.20.147.111</property>
<property name="schema">amoeba_study</property>

<!-- 用于登陆mysql的用户名 -->
<property name="user">root</property>

<!-- 用于登陆mysql的密码 -->
<property name="password"></property>

</factoryConfig>

<!-- ObjectPool实现类 -->
<poolConfig class="com.meidusa.amoeba.net.poolable.PoolableObjectPool">
<property name="maxActive">200</property>
<property name="maxIdle">200</property>
<property name="minIdle">10</property>
<property name="minEvictableIdleTimeMillis">600000</property>
<property name="timeBetweenEvictionRunsMillis">600000</property>
<property name="testOnBorrow">true</property>
<property name="testWhileIdle">true</property>
</poolConfig>
</dbServer>
</dbServerList>

以上是proxy与后端各mysql数据库服务器配置信息,具体配置见注释很明白了

最后配置读写分离策略:

[xhtml] view plaincopyprint?

  1. <queryRouter class="com.meidusa.amoeba.mysql.parser.MysqlQueryRouter">
  2. <property name="LRUMapSize">1500</property>
  3. <property name="defaultPool">server1</property>
  4. <property name="writePool">server1</property>
  5. <property name="readPool">server2</property>
  6. <property name="needParse">true</property>
  7. </queryRouter>

<queryRouter class="com.meidusa.amoeba.mysql.parser.MysqlQueryRouter">
<property name="LRUMapSize">1500</property>
<property name="defaultPool">server1</property>
<property name="writePool">server1</property>
<property name="readPool">server2</property>
<property name="needParse">true</property>
</queryRouter>

从以上配置不然发现,写操作路由到server1(master),读操作路由到server2(slave)

3)启动amoeba

在命令行里运行D:/openSource/amoeba-mysql-1.2.0-GA/amoeba.bat即可:

log4j:WARN log4j config load completed from file:D:/openSource/amoeba-mysql-1.2.0-GA/conf/log4j.xml
log4j:WARN ip access
config load completed from
file:D:/openSource/amoeba-mysql-1.2.0-GA/conf/access_list.conf
2010-07-03
09:55:33,821 INFO  net.ServerableConnectionManager - Server listening on
0.0.0.0/0.0.0.0:8066.
三.client端调用与测试

1)编写client调用程序

具体程序细节就不详述了,只是一个最普通的基于mysql driver的jdbc的数据库操作程序

2)配置数据库连接

本client基于c3p0,具体数据源配置如下:

[xhtml] view
plain
copyprint?

  1. <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
  2. destroy-method="close">
  3. <property name="driverClass" value="com.mysql.jdbc.Driver" />
  4. <property name="jdbcUrl" value="jdbc:mysql://localhost:8066/amoeba_study" />
  5. <property name="user" value="root" />
  6. <property name="password" value="root" />
  7. <property name="minPoolSize" value="1" />
  8. <property name="maxPoolSize" value="1" />
  9. <property name="maxIdleTime" value="1800" />
  10. <property name="acquireIncrement" value="1" />
  11. <property name="maxStatements" value="0" />
  12. <property name="initialPoolSize" value="1" />
  13. <property name="idleConnectionTestPeriod" value="1800" />
  14. <property name="acquireRetryAttempts" value="6" />
  15. <property name="acquireRetryDelay" value="1000" />
  16. <property name="breakAfterAcquireFailure" value="false" />
  17. <property name="testConnectionOnCheckout" value="true" />
  18. <property name="testConnectionOnCheckin" value="false" />
  19. </bean>

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="com.mysql.jdbc.Driver" />
<property name="jdbcUrl" value="jdbc:mysql://localhost:8066/amoeba_study" />
<property name="user" value="root" />
<property name="password" value="root" />
<property name="minPoolSize" value="1" />
<property name="maxPoolSize" value="1" />
<property name="maxIdleTime" value="1800" />
<property name="acquireIncrement" value="1" />
<property name="maxStatements" value="0" />
<property name="initialPoolSize" value="1" />
<property name="idleConnectionTestPeriod" value="1800" />
<property name="acquireRetryAttempts" value="6" />
<property name="acquireRetryDelay" value="1000" />
<property name="breakAfterAcquireFailure" value="false" />
<property name="testConnectionOnCheckout" value="true" />
<property name="testConnectionOnCheckin" value="false" />
</bean>

值得注意是,client端只需连到proxy,与实际的数据库没有任何关系,因此jdbcUrl、user、password配置都对应于amoeba暴露出来的配置信息

3)调用与测试

首先插入一条数据:insert into zone_by_id(id,name) values(20003,‘name_20003‘)

通过查看master机上的日志/var/lib/mysql/mysql_log.log:

100703 11:58:42       1 Query       set names latin1
                     
1 Query       SET NAMES latin1
                      1 Query       SET
character_set_results = NULL
                      1 Query       SHOW
VARIABLES
                      1 Query       SHOW
COLLATION
                      1 Query       SET
autocommit=1
                      1 Query       SET
sql_mode=‘STRICT_TRANS_TABLES‘
                      1 Query       SHOW
VARIABLES LIKE ‘tx_isolation‘
                      1 Query       SHOW FULL
TABLES FROM `amoeba_study` LIKE ‘PROBABLYNOT‘
                      1
Prepare     [1] insert into zone_by_id(id,name)
values(?,?)
                      1 Prepare     [2] insert into
zone_by_id(id,name) values(?,?)          
                      1
Execute     [2] insert into zone_by_id(id,name) values(20003,‘name_20003‘)

得知写操作发生在master机上

通过查看slave机上的日志/var/lib/mysql/mysql_log.log:

100703 11:58:42       2 Query       insert into zone_by_id(id,name)
values(20003,‘name_20003‘)

得知slave同步执行了这条语句

然后查一条数据:select t.name from zone_by_id t where t.id = 20003

通过查看slave机上的日志/var/lib/mysql/mysql_log.log:

100703 12:02:00      33 Query       set names latin1
                    
33 Prepare     [1] select t.name from zone_by_id t where t.id =
?
                     33 Prepare     [2] select t.name from zone_by_id t
where t.id = ?   
                     33 Execute     [2] select t.name from
zone_by_id t where t.id = 20003

得知读操作发生在slave机上

并且通过查看slave机上的日志/var/lib/mysql/mysql_log.log发现这条语句没在master上执行

通过以上验证得知简单的master-slave搭建和实战得以生效

时间: 2024-08-06 03:45:26

构建高性能web之路------mysql读写分离实战的相关文章

mysql读写分离实战

http://blog.csdn.net/cutesource/article/details/5710645 mycat http://code.taobao.org/svn/openclouddb/

【读书笔记】2016.12.10 《构建高性能Web站点》

本文地址 分享提纲: 1. 概述 2. 知识点 3. 待整理点 4. 参考文档 1. 概述 1.1)[该书信息] <构建高性能Web站点>: -- 百度百科 -- 本书目录: 第1章 绪论 1.1 等待的真相 1.2 瓶颈在哪里 1.3 增加带宽 1.4 减少网页中的HTTP请求 1.5 加快服务器脚本计算速度 1.6 使用动态内容缓存 1.7 使用数据缓存 1.8 将动态内容静态化 1.9 更换Web服务器软件 1.10 页面组件分离 1.11 合理部署服务器 1.12 使用负载均衡 1.1

《构建高性能web站点》随笔 无处不在的性能问题

前言– 追寻大牛的足迹,无处不在的“性能”问题. 最近在读郭欣大牛的<构建高性能Web站点>,读完收益颇多.作者从HTTP.多级缓存.服务器并发策略.数据库.负载均衡.分布式文件系统多个方面娓娓道来,洋洋洒洒,甚是精彩,想来让人心旷神怡.     但“纸上得来终觉浅,绝知此事要躬行”,要消化本书的内容,绝不是一件简单的事情,更重要的还是实践.在实践和学习的过程中,我会把自己的经验和感悟分享出来,一方面权当做笔记,另一方面,对于后来的童鞋,希望能提供一丝一毫的帮助,不胜欣慰.     由于是读书

构建高性能Web站点(修订版)笔记

构建高性能Web站点(修订版)2012.6 p14 '反馈机制':逐包确认 --> 小batch连续发送 一定需要全局编址吗?(可以使用邻居路由+端到端IBE) 电磁波速度:铜线中电信号2.3*10^8,光纤约2*10^8(全反射增加了传输距离) 系统负载:/proc/loadavg 上下文切换:Nmon IOWait(注意一点:磁盘IO是串行的!) 减少系统调用... ZeroCopy?AIO? strace:每次请求都要检测.htaccess?(哦,设置了AllowOverride all)

Mysql-Proxy实现mysql读写分离、负载均衡 (转)

在mysql中实现读写分离.负载均衡,用Mysql-Proxy是很容易的事,不过大型处理对于性能方面还有待提高,主要配置步骤如下: 1.1. mysql-proxy安装 MySQL Proxy就是这么一个中间层代理,简单的说,MySQL Proxy就是一个连接池,负责将前台应用的连接请求转发给后台的数据库,并且通过使用lua脚本,可以实现复杂的连接控制和过滤,从而实现读写分离和负 载平衡.对于应用来说,MySQL Proxy是完全透明的,应用则只需要连接到MySQL Proxy的监听端口即可.当

mysql 读写分离

mysql-proxy:简称mysql读写分离:主要目的是为了提高web站点的访问速度. 首先搭建mysql主从,参考:http://syklinux.blog.51cto.com/9631548/1737317 下载mysql-proxy: cd /usr/local/src wget http://cdn.mysql.com/archives/mysql-proxy/mysql-proxy-0.8.5-linux-glibc2.3-x86-64bit.tar.gz tar zxvf mysq

mycat实现MySQL读写分离

mycat实现MySQL读写分离 mycat是什么 Mycat是一个开源的分布式数据库系统,但是由于真正的数据库需要存储引擎,而Mycat并没有存储引擎,所以并不是完全意义的分布式数据库系统.Mycat是数据库中间件,就是介于数据库与应用之间,进行数据处理与交互的中间服务.对数据进行分片处理之后,从原有的一个库,被切分为多个分片数据库,所有的分片数据库集群构成了整个完整的数据库存储. Mycat的几个典型的应用场景: 单纯的读写分离,此时配置最为简单,支持读写分离,主从切换: 分表分库,对于超过

mysql读写分离amoeba实现

用amoeba配合mysql主从构建mysql读写分离 1 mysql主从配置 mysql master192.168.11.177 mysql slave192.168.11.178 amoeba 主机192.168.11.179 俩台虚拟机上 yum install mysqlmysql-serevr mysql-devel(没有用,防止以后用) /etc/init.d/mysqldstart mysqladmin -u rootpassword '123456' chkconfig mys

构建高性能web站点

以下为阅读<构建高性能web站点>郭欣 著 第一章的重点总结 1.等待的真相 a) 在用户等待的时间里,大概发生了以下几部分时间: i. 数据在网络上传输的时间:包括两个部分,浏览器端主机发出请求经过网络到达服务器的时间,服务器回应数据经过网络到达浏览器主机的时间.也称为响应时间,他的决定因素主要包括发送的数据量和网络带宽.站点服务器处理请求并回应数据的时间- ii. 站点服务器处理请求并生成回应数据的时间.主要消耗在服务器端,包括非常多的环节,我们一般用"每秒处理请求数"