zoukankan      html  css  js  c++  java
  • 构建高性能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 repl@10.20.147.111 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 'repl@10.20.147.110: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):

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

     

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

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

     

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

    最后配置读写分离策略:

    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>  

     

    从以上配置不然发现,写操作路由到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,具体数据源配置如下:

    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>  

     

    值得注意是,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搭建和实战得以生效

  • 相关阅读:
    动态生成 Excel 文件供浏览器下载的注意事项
    JavaEE 中无用技术之 JNDI
    CSDN 泄露用户密码给我们什么启示
    刚发布新的 web 单点登录系统,欢迎下载试用,欢迎提建议
    jQuery jqgrid 对含特殊字符 json 数据的 Java 处理方法
    一个 SQL 同时验证帐号是否存在、密码是否正确
    PostgreSQL 数据库在 Windows Server 2008 上安装注意事项
    快速点评 Spring Struts Hibernate
    Apache NIO 框架 Mina 使用中出现 too many open files 问题的解决办法
    解决 jQuery 版本升级过程中出现 toLowerCase 错误 更改 doctype
  • 原文地址:https://www.cnblogs.com/firstdream/p/7850866.html
Copyright © 2011-2022 走看看