系统变迁之五--mysql读写分离

数据库设定了主从同步后,单纯的数据多点存放已经不能满足我了(O(∩_∩)O)...
读写分离一直有各种方案,MySQL-Proxy也好,amoeba也罢,或者其他的中间件,都是在DB和application之间引入一个proxy,使用proxy来处理application中对DB的各种操作。
还有一种伪读写分离的方案,在项目中配置多个数据源,不同的操作连接不同的数据源。。。
不过我更倾向于在驱动层去处理这个问题,不太想再去额外维护一个中间件。而mysql的驱动目前已经支持使用ReplicationDriver来替代Driver,实现读写分离。

ReplicationDriver

官方关于ReplicationDriver的说明可以参考这里:http://dev.mysql.com/doc/connector-j/5.1/en/connector-j-master-slave-replication-connection.html

ReplicationDriver驱动分离的机制是靠判断connection.setReadOnly(true)来决定是否访问从库,而Spring的事务管理,可以使用@Tranactional(readonly=true)来设置连接是否为只读,基本上就这些,看起来挺简单吧...一路还是不断踩坑,且听俺慢慢道来。。。

先提一下,数据库连接池bonecp是不支持使用ReplicationDriver做读写分离的。最初项目为了求快和求简,用了bonecp(配制简单,块头小),不过在引入ReplicationDriver的时候,却踩了坑,无论怎么配置都是访问的主库。后面切换为druid才解决,关于淘宝开源的数据库连接池druid介绍,可以参考这里:https://github.com/alibaba/druid/wiki

在数据库连接池中配置ReplicationDriver
  • 首先引入druid及ReplicationDriver的依赖

      
          com.alibaba
          druid
          ${druid-version}
      
       
          
          mysql    
          mysql-connector-java    
          5.1.39
     
    
  • 数据库连接池配置

          
              
             
             
             
         
         
            
        
        
            
            
    
            
            
            
           
            
            
            
            
            
            
        
     
    

每个属性的说明可以参考这里:
https://github.com/alibaba/druid/wiki/DruidDataSource%E9%85%8D%E7%BD%AE%E5%B1%9E%E6%80%A7%E5%88%97%E8%A1%A8

  • 注意url中,mysql的数据库连接要改成 jdbc:mysql:replication:// 开头,而后面的IP地址,则依照masterIP:port,slave1IP:port,slave2IP:port的顺序往下写,主库在先,从库在后。
spring事务中对于连接的处理
  • 做读写分离,首先需要梳理哪些方法是只读操作,哪些方法是读写一体或只写操作。而对于比较关键的只读操作,也不建议直接迁移到从库,毕竟主从复制是有一定的时间延迟的。
  • 既然提到事务了,如果在一个事务中涉及到了多张表的操作,一定要看下mysql的autocommit选项是否关闭,否则会造成回滚失败
系统变迁之五--mysql读写分离_第1张图片
Paste_Image.png
  • 而且要注意,这个命令只针对当前用户,如果需要全局生效,则需要使用global关键字
系统变迁之五--mysql读写分离_第2张图片
Paste_Image.png
  • 还要注意的是,这个选项对于mysql的root用户是不生效的。。。而且,如果是使用spring统一管理数据库连接,这块spring是在DataSourceTransactionManager.java中默认设置为false的,如下:

    // switch to manual commit if necessary. this is very expensive in some jdbc drivers,
    // so we don't want to do it unnecessarily (for example if we've explicitly
    // configured the connection pool to set it already).
    if (con.getautocommit()) {
        txobject.setmustrestoreautocommit(true);
    if (logger.isdebugenabled()) {
      logger.debug("switching jdbc connection [" + con + "] to manual commit");
    }
    con.setautocommit(false);
    }
    
  • 代码级别的设置:
    在只需要访问读库的方法上,添加注解 ,搞定,收工。。。

     @Transactional(readOnly = true,...) 
    
    • 此注解只能在public方法上使用才会生效
    • readOnly默认为false的,故对于需要访问主库的,这个属性可以不设置
附上druid中的配置监控,方便查看统计
  • 先晒两张监控图
系统变迁之五--mysql读写分离_第3张图片
Paste_Image.png
系统变迁之五--mysql读写分离_第4张图片
Paste_Image.png

druid跟其他数据库连接池除了在连接上面做了很多优化之外,亮点就是在监控这块了

  • 配置druid web监控
    • 在项目的web.xml中加入filter配置

       
           
           DruidWebStatFilter    
           com.alibaba.druid.support.http.WebStatFilter    
                   
                exclusions        
                *.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*    
               
                   
                profileEnable        
                true    
           
        
            
               DruidWebStatFilter    
               /*
       
      
    • 在web.xml中加入servlet配置

        
            
             DruidStatView    
             com.alibaba.druid.support.http.StatViewServlet    
                     
                            
                    resetEnable        
                    true    
                
                    
                            
                    loginUsername        
                    druid    
                
                    
                            
                    loginPassword        
                    ****    
            
        
      
            
            DruidStatView    
            /druid/*
        
      

重启后,直接访问http://ip/domainname[:port]/appname/druid ,使用上述指定的用户名及密码就可以登录了,可以查看sql及bean相关的统计,以及慢sql等统计数据。

你可能感兴趣的:(系统变迁之五--mysql读写分离)