1. 程式人生 > >mysql主從,spring 讀寫分離

mysql主從,spring 讀寫分離

1,mysql的複製依賴bin-log日誌檔案,bin-log記錄了所有在master端執行的 ddl/dml/事務操作序列,並同步到slave端,slave根據日誌復現序列,即完成同步; 複製流程: 1,slave上面的io執行緒連線上master,並請求指定的日誌檔案的指定位置之後的內容; 2,master接收到來自slave的io執行緒的請求後,通過負責複製的io執行緒根據請求資訊讀取指定日誌 指定位置之後的日誌資訊,返回給slave端的io執行緒 3,slave的io執行緒接收到資訊後,將接收到的日誌內容一次寫入大slave端的 relay-log 檔案(mysql-relay-bin.xxxxxx)的最末端 4,slave的sql執行緒檢測到relay-Log中新增加了內容後,會立馬解析該log檔案中的新增內容,並執行語句;

主從配置: 1,備份主資料庫,並同步到從資料庫 2,開啟主資料庫bin-log日誌(my.cn) 3,配置從資料庫主資料庫相關資訊

具體步驟: 前提:拷貝主資料庫資料到從資料庫。

1,主3306 my.cnf server-id=1 //資料庫唯一標識 log-bin=/data/3306/log-bin/mysql-bin //二進位制日誌檔案 log-bin-index=/data/3306/log-bin/mysql-bin-index //二進位制索引檔案

2,啟動主資料庫 3,在mysql命令列檢視主資料庫狀態: mysql>show master status; +------------------+----------+--------------+------------------+-------------------+ | File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+-------------------+ | mysql-bin.000020 |      120 |              |                  |                   | +------------------+----------+--------------+------------------+-------------------+

4,配置從資料庫 從my.cnf relay-log=/data/3307/relay-log/relay-bin relay-log-index=/data/3307/relay-log/relay-bin-index relay-log-info-file=/data/3307/relay-log/relay-log.info server-id=2

5,啟動從資料庫 6,在從資料庫執行查詢語句: change master to master_host='119.23.19.127', //主資料ip master_port=3306, master_user='root', master_password='root', master_log_file='mysql-bin.000001',//master產生的log-bin 日誌 master_log_pos=0;

change master to master_host='119.23.19.127', master_port=3306, master_user='root', master_password='root', master_log_file='mysql-bin.000001', master_log_pos=0;

6,開啟主從複製 start slave;

show slave status;

============java讀寫分離

xml:

    <!-- 配置資料來源 -->     <bean name="dataSourceMaster" class="com.alibaba.druid.pool.DruidDataSource"         init-method="init" destroy-method="close">         <property name="driverClassName" value="${jdbc.driver}" />         <property name="url" value="${jdbc.url}" />         <property name="username" value="${jdbc.username}" />         <property name="password" value="${jdbc.password}" />         //......     </bean>          <!-- 配置資料來源 -->     <bean name="dataSourceRead" class="com.alibaba.druid.pool.DruidDataSource"         init-method="init" destroy-method="close">         <property name="driverClassName" value="${jdbc.driver}" />         <property name="url" value="${jdbc.url2}" />         <property name="username" value="${jdbc.username2}" />         <property name="password" value="${jdbc.password2}" />         //.....              </bean>     <!--資料來源選擇器  -->     <bean name="routingDataSource" class="com.edu.utils.EduRoutingDataSource">         <!--資料來源集合,spring 會根據傳入key 去找對應資料來源  -->         <property name="targetDataSources">             <map>                 <entry key="dbMaster" value-ref="dataSourceMaster"></entry>                 <entry key="dbRead" value-ref="dataSourceRead"></entry>             </map>         </property>     </bean>          <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">         <property name="dataSource" ref="routingDataSource" />         <!-- 設定欄位為空時,也返回該欄位  -->         <property name="configLocation" value="classpath:configuration.xml"></property>         <!-- 自動掃描entity目錄, 省掉Configuration.xml裡的手工配置 -->         <property name="mapperLocations">             <list>                 <value>classpath:com/edu/dao/mapperxml/*.xml</value>                 <value>classpath:com/edu/dao/mapperxml/*/*.xml</value>             </list>         </property>              </bean>     

    <!-- 配置事務管理器 -->     <bean id="transactionManager"         class="org.springframework.jdbc.datasource.DataSourceTransactionManager">         <property name="dataSource" ref="routingDataSource" />     </bean>

DbContext.java /**  * 要選擇的資料放進執行緒變數裡  * @author Administrator  *  */ public class DbContext {     private static ThreadLocal<String> dbPools=new ThreadLocal<String>();     public static void set(String db){         dbPools.set(db);     }     public static String get(){         return dbPools.get();     } }

DbHandler.java import java.lang.reflect.Method;

import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint; import org.springframework.stereotype.Component;

/**  * 資料來源選擇 前置通知  * @author   *  */ @Component @Aspect public class DbHandler{          /**     Description: 配置切入點,該方法無方法體,主要為方便同類中其他方法使用此處配置的切入點;攔截暴露出來的服務類介面public方法<p>       void     */     @Pointcut("execution(public *..*Service.*(..))")     public void face(){                  }          @Before("face()")      public void dbBefore(JoinPoint joinPoint)                   throws Throwable {            MethodInvocationProceedingJoinPoint methodJoinPoint = (MethodInvocationProceedingJoinPoint) joinPoint;         String className = methodJoinPoint.getTarget().getClass().getName();         String methodName = methodJoinPoint.getSignature().getName();          Method method;                       try {                 Class<?>[] parameterTypes = ((MethodSignature)methodJoinPoint.getSignature()).getMethod().getParameterTypes();                 method = methodJoinPoint.getTarget().getClass().getMethod(methodName, parameterTypes);                 DbReadAnnotation dbAnnotation = method.getAnnotation(DbReadAnnotation.class);                 if(dbAnnotation==null){                     DbContext.set(EduRoutingDataSource.dbMasterDataSource);                 }else{                     DbContext.set(EduRoutingDataSource.dbReadDataSource);                 }             }catch(Exception e){             }         }   }

EduRoutingDataSource.java import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; /**  * 資料來源選擇器  * @author Administrator  *  */ public class EduRoutingDataSource extends AbstractRoutingDataSource {     //讀和寫資料來源標識     public static final String dbMasterDataSource ="dbMaster";     //只讀資料來源標識     public static final String dbReadDataSource ="dbRead";          /**      * spring 要使用到資料來源時會回撥這個方法,獲取要使用的資料來源      */     @Override     protected Object determineCurrentLookupKey() {         return DbContext.get()==null?EduRoutingDataSource.dbMasterDataSource:DbContext.get();     }

}

DbReadAnnotation.java

import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /**  * 資料來源選擇 註解  * 方法打上這標籤都用讀的 資料來源  * @author Administrator  *  */ @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface DbReadAnnotation { }