最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

springboot多數(shù)據(jù)源配合docker部署mysql主從實現(xiàn)讀寫分離效果

 更新時間:2021年09月24日 09:12:40   作者:coffeebabe  
這篇文章主要介紹了springboot多數(shù)據(jù)源配合docker部署mysql主從實現(xiàn)讀寫分離,通過使用docker獲取mysql鏡像,具體內(nèi)容詳情跟隨小編一起看看吧

一、使用docker部署mysql主從 實現(xiàn)主從復(fù)制

此次使用的是windows版本docker,mysql版本是5.7

1、使用docker獲取mysql鏡像

docker pull mysql:5.7.23 #拉取鏡像文件

docker images #查看鏡像文件

2、使用docker運行mysql master

docker run --name mysql-master --privileged=true -v F:\dockerV\mysql:/var/lib/mysql -p 3307:3306 -e MYSQL_ROOT_PASSWORD=654321 -d mysql:5.7.23
  • --name 容器名稱mysql-master
  • --privileged 指定了當(dāng)前容器是否真正的具有root權(quán)限,所謂的root權(quán)限是指具有宿主機的root權(quán)限,而不僅僅只是在容器內(nèi)部有root權(quán)限
  • -v 將系統(tǒng)的F:\dockerV\mysql掛載到容器的/var/lib/mysql,注意是將宿主機 掛載到 容器內(nèi)部,而不是將容器內(nèi)部掛載到宿主機
  • -p 表示宿主機上的某個端口映射到docker容器內(nèi)的某個端口,這里也就是將宿主機的3307端口映射到容器內(nèi)部的3306端口
  • -e 表示指定當(dāng)前容器運行的環(huán)境變量,該變量一般在容器內(nèi)部程序的配置文件中使用,而在外部運行容器指定該參數(shù)。這里的MYSQL_ROOT_PASSWORD表示容器內(nèi)部的MySQL的啟動密碼
  • -d 后臺運行,鏡像文件為mysql:5.7.23

接下來進(jìn)入容器內(nèi)部,修改配置,使其作為mysql master運行

docker exec -it mysql-master bash #進(jìn)入容器內(nèi)部

配置mysql master,修改mysql.cnf

使用vim修改mysql.cnf,沒有安裝vim會提示bash: vi: command not found 則需要安裝vim

apt-get install vim

apt-get update

apt-get install vim

vim mysqld.cnf #修改cnf文件,添加 server-id 表示master服務(wù)標(biāo)識,同一局域網(wǎng)內(nèi)注意要唯一 和 log-bin=mysql-bin 開啟二進(jìn)制日志功能,可以隨便取,用來完成主從復(fù)制

修改完成mysql的配置后,需要重啟服務(wù)生效

service MySQL restart # 重啟mysql服務(wù)時會使得docker容器停止,我們還需要docker start mysql-master啟動容器

docker start mysql-master #啟動容器

連接mysql客戶端,創(chuàng)建用來完成主從復(fù)制的賬號

mysql -uroot -p654321 #連接mysql

為從服務(wù)器創(chuàng)建一個可以用來操作master服務(wù)器的賬戶,也就是創(chuàng)建一個專門用來復(fù)制binlog的賬號,并且賦予該賬號復(fù)制權(quán)限,其命令如下

grant replication slave on *.* to 'slaveaccount'@'%' identified by '654321'; #賬號slaveaccount 密碼654321

flush privileges; #刷新用戶權(quán)限表

show master status #查看mysql master的狀態(tài)

記錄下上的position和file 在創(chuàng)建MySQL slave配置時會用到

到這里mysql master 已經(jīng)配置完成了

3、使用docker運行mysql slave

docker run --name mysql-slave --privileged=true -v F:\dockerV\mysql-slave:/var/lib/mysql -p 3308:3306 --link mysql-master:master -e MYSQL_ROOT_PASSWORD=654321 -d mysql:5.7.23

mysql slave 的參數(shù)主要和master有兩點不同

  • 所映射的宿主機的端口號不能與master容器相同,因為其已經(jīng)被master容器占用;
  • 必須加上--link參數(shù),其后指定了當(dāng)前容器所要連接的容器,mysql-master表示所要連接的容器的名稱,master表示為該容器起的一個別名,通俗來講,就是slave容器通過這兩個名稱都可以訪問到master容器。這么做的原因在于,如果master與slave不在同一個docker network中,那么這兩個容器相互之間是沒法訪問的。
docker exec -it mysql-slave /bin/bash #進(jìn)入mysql salve容器

vim mysqld.cnf #修改cnf文件,添加 server-id 表示slave服務(wù)標(biāo)識,如果此salve需要作為其他mysql的主,那么就需要配置log-bin=mysql-bin

service MySQL restart # 重啟mysql服務(wù)時會使得docker容器停止,我們還需要docker start mysql-slave啟動容器

docker start mysql-master #啟動容器

mysql -uroot -proot #連接mysql服務(wù)

配置mysql slave 使其以slave模式運行

change master to master_host='172.17.0.2', master_user='slaveaccount', master_password='654321', master_port=3306, master_log_file='mysql-bin.000001', master_log_pos=2272, master_connect_retry=30;

注意:這一步主要在slave是配置master的信息,包括 master的 地址、端口、賬號、密碼、log文件、log文件偏移量、重試。下面介紹這些參數(shù)值從何獲取

獲取master_host,使用docker inspect mysql-master查看master容器元數(shù)據(jù)。其中 IPAdress是master_host

  • 獲取master_port,是運行master映射容器內(nèi)部的端口,這里就是3306
  • 獲取master_user和master_password,是第一步中在master中創(chuàng)建的slave賬號
  • 獲取master_log_file和master_log_pos,是配置master中最后一步使用show master status獲取的文件和偏移量
  • 獲取master_connect_retry,是slave重試連接master動作前的休眠時間,單位s,默認(rèn)60s
start slave; #以slave模式運行

show salve status \G; #查看slave的狀態(tài)

可以看到,Slave_IO_Running:YES和Slave_SQL_Running:YES 證明此時主從復(fù)制已經(jīng)就緒,slave配置到此完成

4、驗證主從復(fù)制效果

  • 這里我們在連接master,并創(chuàng)建一張表,添加數(shù)據(jù),在從庫查看數(shù)據(jù)是否同步。
  • 在主庫創(chuàng)建數(shù)據(jù),并在從庫查看數(shù)據(jù)是否同步成功。
mysql> create database test;
Query OK, 1 row affected (0.01 sec)

mysql> use test;
Database changed

mysql> create table t_user(id bigint, name varchar(255));
Query OK, 0 rows affected (0.02 sec)

mysql> insert into t_user(id, name) value (1, 'cgg');
Query OK, 1 row affected (0.01 sec)
mysql> select * from test.t_user;
+------+------+
| id   | name |
+------+------+
|    1 | cgg |
+------+------+
1 row in set (0.00 sec)

5、mysql主從復(fù)制原理

  • 主庫db的更新事件(update、insert、delete)被寫到binlog
  • 主庫創(chuàng)建一個binlog dump thread,把binlog的內(nèi)容發(fā)送到從庫
  • 從庫啟動并發(fā)起連接,連接到主庫
  • 從庫啟動之后,創(chuàng)建一個I/O線程,讀取主庫傳過來的binlog內(nèi)容并寫入到relay log
  • 從庫啟動之后,創(chuàng)建一個SQL線程,從relay log里面讀取內(nèi)容,從Exec_Master_Log_Pos位置開始執(zhí)行讀取到的更新事件,將更新內(nèi)容寫入到slave的db

二、springboot項目多數(shù)據(jù)源配置,實現(xiàn)讀寫分離

1、主從多數(shù)據(jù)源配置

yml配置

server:
  port: 8888
  servlet:
    encoding:
      charset: UTF-8
      force: true
      enabled: true
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
    url: jdbc:mysql://127.0.0.1:3307/test?serverTimezone=GMT%2B8&characterEncoding=utf-8&autoReconnect=true&failOverReadOnly=false&useSSL=false
    username: root
    password: 654321
slave:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
    url: jdbc:mysql://127.0.0.1:3308/test?serverTimezone=GMT%2B8&characterEncoding=utf-8&autoReconnect=true&failOverReadOnly=false&useSSL=false
    username: root
    password: 654321

數(shù)據(jù)源配置

/**
 * @author cgg
 **/
@Configuration
@EnableTransactionManagement
public class DynamicDataSourceConfig {


    @Bean(name = "slaveDatasource")
    @ConfigurationProperties(prefix = "slave.datasource")
    public DataSource dbSlave() {
        return DruidDataSourceBuilder.create().build();
    }

    @Bean(name = "dataSource")
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource dbMaster() {
        return DruidDataSourceBuilder.create().build();
    }


    @Bean
    @Primary
    public DataSource multipleDataSource(@Qualifier("dataSource") DataSource db,
                                         @Qualifier("slaveDatasource") DataSource slaveDatasource) {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        Map<Object, Object> targetDataSources = new HashMap<>(16);
        targetDataSources.put("dataSource", db);
        targetDataSources.put("slaveDatasource", slaveDatasource);
        dynamicDataSource.setTargetDataSources(targetDataSources);
        //設(shè)置默認(rèn)數(shù)據(jù)源為從庫,如果寫操作業(yè)務(wù)多,可以默認(rèn)設(shè)置為主庫
        dynamicDataSource.setDefaultTargetDataSource(slaveDatasource);
        return dynamicDataSource;
    }

    @Bean("sqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();
        sqlSessionFactory.setDataSource(multipleDataSource(dbSlave(), dbMaster()));
        MybatisConfiguration configuration = new MybatisConfiguration();
        configuration.setJdbcTypeForNull(JdbcType.NULL);
        configuration.setMapUnderscoreToCamelCase(true);
        configuration.setCacheEnabled(false);
        sqlSessionFactory.setConfiguration(configuration);
        sqlSessionFactory.setMapperLocations((new PathMatchingResourcePatternResolver()).getResources(DEFAULT_MAPPER_LOCATION));
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        paginationInterceptor.setOverflow(false);
        paginationInterceptor.setLimit(-1);
        paginationInterceptor.setCountSqlParser(tenantSqlParserCountOptimize());
        Interceptor[] plugins = new Interceptor[]{new ShardTableInterceptor(), paginationInterceptor};
        sqlSessionFactory.setPlugins(plugins);
        return sqlSessionFactory.getObject();
    }

}

/**
 * 動態(tài)數(shù)據(jù)源
 *
 * @author cgg
 **/
@Slf4j
public class DynamicDataSource  extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        return DbContextHolder.getDbType();
    }
}

2、配置切面控制主從數(shù)據(jù)源切換、讀從庫寫主庫,實現(xiàn)讀寫分離

aop切面

/**
 * @author cgg
 **/
@Component
@Order(value = -100)
@Slf4j
@Aspect
public class DataSourceSwitchAspect {

    //master 包下的操作都是操作主庫業(yè)務(wù)
    @Pointcut("execution(* com.master..*.*(..))")
    private void db1Aspect() {
    }

    //slave 包下的操作都是操作從庫業(yè)務(wù)
    @Pointcut("execution(* com.slave.*.*(..))")
    private void db2Aspect() {
    }


    @Before("db1Aspect()")
    public void dbMaster() {
        log.debug("切換到Master 數(shù)據(jù)源...");
        DbContextHolder.setDbType("dataSource");
    }

    @Before("db2Aspect()")
    public void dbSlave() {
        log.debug("切換到Slave 數(shù)據(jù)源...");
        DbContextHolder.setDbType("slaveDatasource");
    }
}


/**
 * @author cgg
 **/
public class DbContextHolder {
    private static final ThreadLocal contextHolder = new ThreadLocal<>();
    /**
     * 設(shè)置數(shù)據(jù)源
     * @param dbType
     */
    public static void setDbType(String dbType) {
        contextHolder.set(dbType);
    }

    /**
     * 取得當(dāng)前數(shù)據(jù)源
     * @return
     */
    public static String getDbType() {
        return (String) contextHolder.get();
    }

    /**
     * 清除上下文數(shù)據(jù)
     */
    public static void clearDbType() {
        contextHolder.remove();
    }
}

3、驗證讀寫分離效果

使用接口調(diào)用不同接口,切點會自動切換數(shù)據(jù)源,這里寫庫接口只會操作主庫,讀庫接口會操作從庫。實現(xiàn)讀寫分離

到此這篇關(guān)于springboot多數(shù)據(jù)源配合docker部署mysql主從實現(xiàn)讀寫分離的文章就介紹到這了,更多相關(guān)springboot讀寫分離內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java用POI解析excel并獲取所有單元格數(shù)據(jù)的實例

    Java用POI解析excel并獲取所有單元格數(shù)據(jù)的實例

    下面小編就為大家?guī)硪黄狫ava用POI解析excel并獲取所有單元格數(shù)據(jù)的實例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-10-10
  • springboot使用mybatis開啟事務(wù)回滾

    springboot使用mybatis開啟事務(wù)回滾

    本文主要介紹了springboot使用mybatis開啟事務(wù)回滾,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02
  • SpringBoot文件上傳與下載功能實現(xiàn)詳解

    SpringBoot文件上傳與下載功能實現(xiàn)詳解

    文件上傳與下載是Web應(yīng)用開發(fā)中常用的功能之一。接下來我們將討論如何在Spring?Boot的Web應(yīng)用開發(fā)中,如何實現(xiàn)文件的上傳與下載,感興趣的可以了解一下
    2022-10-10
  • SpringBoot 鉤子接口的實現(xiàn)代碼

    SpringBoot 鉤子接口的實現(xiàn)代碼

    本文主要介紹了SpringBoot 鉤子接口,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-08-08
  • TransmittableThreadLocal通過javaAgent實現(xiàn)線程傳遞并支持ForkJoin

    TransmittableThreadLocal通過javaAgent實現(xiàn)線程傳遞并支持ForkJoin

    這篇文章主要介紹了TransmittableThreadLocal通過javaAgent實現(xiàn)線程傳遞并支持ForkJoin詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • 用dom4j生成xml,去掉xml頭的方法

    用dom4j生成xml,去掉xml頭的方法

    今天小編就為大家分享一篇用dom4j生成xml,去掉xml頭的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-07-07
  • java的Console類的使用方法及實例

    java的Console類的使用方法及實例

    這篇文章主要介紹了java的Console類的使用方法及實例的相關(guān)資料,需要的朋友可以參考下
    2017-07-07
  • Java反射機制的學(xué)習(xí)總結(jié)

    Java反射機制的學(xué)習(xí)總結(jié)

    總的來說,java反射機制是一個很好用的東西,用它可以解決很多死的東西,因為反射機制的靈活行很大,有了他,我們就不要花太多的時間來寫操做數(shù)據(jù)庫的代碼了,而是方法更多的時間在項目的邏輯功能上,這個可以很大的減少開發(fā)時間,而且代碼的可讀性好
    2013-09-09
  • MyBatis執(zhí)行批處理操作的實現(xiàn)示例

    MyBatis執(zhí)行批處理操作的實現(xiàn)示例

    在MyBatis中,批處理操作是一種高效執(zhí)行多條語句的方式,下面就來介紹一下MyBatis執(zhí)行批處理操作的實現(xiàn)示例,具有一定的參考價值,感興趣的可以了解一下
    2024-07-07
  • 通過實例解析java8中的parallelStream

    通過實例解析java8中的parallelStream

    這篇文章主要介紹了通過實例解析java8中的parallelStream,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-11-11

最新評論

木兰县| 邢台市| 乾安县| 济宁市| 凤凰县| 隆安县| 亳州市| 清涧县| 平江县| 紫金县| 余干县| 闻喜县| 兖州市| 边坝县| 朝阳区| 梨树县| 景德镇市| 兰西县| 葵青区| 平阳县| 兴安盟| 五大连池市| 峨眉山市| 正宁县| 屯门区| 永城市| 洛宁县| 五莲县| 扎兰屯市| 汕头市| 光泽县| 新绛县| 古丈县| 土默特右旗| 兴化市| 桑日县| 南充市| 微博| 蛟河市| 涡阳县| 太和县|