溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

MySQL中數(shù)據(jù)源管理和關(guān)系型分庫分表以及列式庫分布式計(jì)算分別指的是什么

發(fā)布時(shí)間:2021-10-08 16:12:02 來源:億速云 閱讀:90 作者:柒染 欄目:MySQL數(shù)據(jù)庫

這篇文章將為大家詳細(xì)講解有關(guān)MySQL中數(shù)據(jù)源管理和關(guān)系型分庫分表以及列式庫分布式計(jì)算分別指的是什么,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。

一、數(shù)據(jù)拆分概念

1、場景描述

隨著業(yè)務(wù)發(fā)展,數(shù)據(jù)量的越來越大,業(yè)務(wù)系統(tǒng)越來越復(fù)雜,拆分的概念邏輯就應(yīng)運(yùn)而生。數(shù)據(jù)層面的拆分,主要解決部分表數(shù)據(jù)過大,導(dǎo)致處理時(shí)間過長,長期占用鏈接,甚至出現(xiàn)大量磁盤IO問題,嚴(yán)重影響性能;業(yè)務(wù)層面拆分,主要解決復(fù)雜的業(yè)務(wù)邏輯,業(yè)務(wù)間耦合度過高,容易引起雪崩效應(yīng),業(yè)務(wù)庫拆分,微服務(wù)化分布式,也是當(dāng)前架構(gòu)的主流方向。

2、基本概念

MySQL中數(shù)據(jù)源管理和關(guān)系型分庫分表以及列式庫分布式計(jì)算分別指的是什么

分區(qū)模式

針對(duì)數(shù)據(jù)表做分區(qū)模式,所有數(shù)據(jù),邏輯上還存在一張表中,但是物理堆放不在一起,會(huì)根據(jù)一定的規(guī)則堆放在不同的文件中。查詢數(shù)據(jù)的時(shí)候必須按照指定規(guī)則觸發(fā)分區(qū),才不會(huì)全表掃描。不可控因素過多,風(fēng)險(xiǎn)過大,一般開發(fā)規(guī)則中都是禁止使用表分區(qū)。

分表模式

單表數(shù)據(jù)量過大,一般情況下單表數(shù)據(jù)控制在300萬,這里的常規(guī)情況是指字段個(gè)數(shù),類型都不是極端類型,查詢也不存在大量鎖表的操作。超過該量級(jí),這時(shí)候就需要分表操作,基于特定策略,把數(shù)據(jù)路由到不同表中,表結(jié)構(gòu)相同,表名遵循路由規(guī)則。

分庫模式

在系統(tǒng)不斷升級(jí),復(fù)雜化場景下,業(yè)務(wù)不好管理,個(gè)別數(shù)據(jù)量大業(yè)務(wù)影響整體性能,這時(shí)候可以考慮業(yè)務(wù)分庫,大數(shù)據(jù)量場景分庫分表,減少業(yè)務(wù)間耦合度,高并發(fā)大數(shù)據(jù)的資源占用情況,實(shí)現(xiàn)數(shù)據(jù)庫層面的解耦。在架構(gòu)層面也可以服務(wù)化管理,保證服務(wù)的高可用和高性能。

常用算法

  • 哈希值取余:根據(jù)路由key的哈希值余數(shù),把數(shù)據(jù)分布到不同庫,不同表;

  • 哈希值分段:根據(jù)路由key的哈希值分段區(qū)間,實(shí)現(xiàn)數(shù)據(jù)動(dòng)態(tài)分布;

這兩種方式在常規(guī)下都沒有問題,但是一旦分庫分表情況下數(shù)據(jù)庫再次飽和,需要遷移,這時(shí)候影響是較大的。

二、關(guān)系型分庫

1、分庫基本邏輯

基于一個(gè)代理層(這里使用Sharding-Jdbc中間件),指定分庫策略,根據(jù)路由結(jié)果,找到不同的數(shù)據(jù)庫,執(zhí)行數(shù)據(jù)相關(guān)操作。

2、數(shù)據(jù)源管理

把需要分庫的數(shù)據(jù)源統(tǒng)一管理起來。

@Configuration
public class DataSourceConfig {
    // 省略數(shù)據(jù)源相關(guān)配置
    /**
     * 分庫配置
     */
    @Bean
    public DataSource dataSource (@Autowired DruidDataSource dataZeroSource,
                                  @Autowired DruidDataSource dataOneSource,
                                  @Autowired DruidDataSource dataTwoSource) throws Exception {
        ShardingRuleConfiguration shardJdbcConfig = new ShardingRuleConfiguration();
        shardJdbcConfig.getTableRuleConfigs().add(getUserTableRule());
        shardJdbcConfig.setDefaultDataSourceName("ds_0");
        Map<String,DataSource> dataMap = new LinkedHashMap<>() ;
        dataMap.put("ds_0",dataZeroSource) ;
        dataMap.put("ds_1",dataOneSource) ;
        dataMap.put("ds_2",dataTwoSource) ;
        Properties prop = new Properties();
        return ShardingDataSourceFactory.createDataSource(dataMap, shardJdbcConfig, new HashMap<>(), prop);
    }
    /**
     * 分表配置
     */
    private static TableRuleConfiguration getUserTableRule () {
        TableRuleConfiguration result = new TableRuleConfiguration();
        result.setLogicTable("user_info");
        result.setActualDataNodes("ds_${1..2}.user_info_${0..2}");
        result.setDatabaseShardingStrategyConfig(new StandardShardingStrategyConfiguration("user_phone", new DataSourceAlg()));
        result.setTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("user_phone", new TableSignAlg()));
        return result;
    }
}

3、指定路由策略

  • 路由到庫

根據(jù)分庫策略的值,基于hash算法,判斷路由到哪個(gè)庫。has算法不同,不但影響庫的操作,還會(huì)影響數(shù)據(jù)入表的規(guī)則,比如偶數(shù)和奇數(shù),導(dǎo)致入表的奇偶性。

public class DataSourceAlg implements PreciseShardingAlgorithm<String> {
    private static Logger LOG = LoggerFactory.getLogger(DataSourceAlg.class);
    @Override
    public String doSharding(Collection<String> names, PreciseShardingValue<String> value) {
        int hash = HashUtil.rsHash(String.valueOf(value.getValue()));
        String dataName = "ds_" + ((hash % 2) + 1) ;
        LOG.debug("分庫算法信息:{},{},{}",names,value,dataName);
        return dataName ;
    }
}
  • 路由到表

根據(jù)分表策略的配置,基于hash算法,判斷路由到哪張表。

public class TableSignAlg implements PreciseShardingAlgorithm<String> {
    private static Logger LOG = LoggerFactory.getLogger(TableSignAlg.class);
    @Override
    public String doSharding(Collection<String> names, PreciseShardingValue<String> value) {
        int hash = HashUtil.rsHash(String.valueOf(value.getValue()));
        String tableName = "user_info_" + (hash % 3) ;
        LOG.debug("分表算法信息:{},{},{}",names,value,tableName);
        return tableName ;
    }
}

上述就是基于ShardingJdbc分庫分表的核心操作流程。

三、列式庫統(tǒng)計(jì)

1、列數(shù)數(shù)據(jù)

在相對(duì)龐大的數(shù)據(jù)分析時(shí),通常會(huì)選擇生成一張大寬表,并且存放到列式數(shù)據(jù)庫中,為了保證高效率執(zhí)行,可能會(huì)把數(shù)據(jù)分到不同的庫和表中,結(jié)構(gòu)一樣,基于多線程去統(tǒng)計(jì)不同的表,然后合并統(tǒng)計(jì)結(jié)果。

MySQL中數(shù)據(jù)源管理和關(guān)系型分庫分表以及列式庫分布式計(jì)算分別指的是什么

基本原理:多線程并發(fā)去執(zhí)行不同的表的統(tǒng)計(jì),然后匯總統(tǒng)計(jì),相對(duì)而言統(tǒng)計(jì)操作不難,但是需要適配不同類型的統(tǒng)計(jì),比如百分比,總數(shù),分組等,編碼邏輯相對(duì)要求較高。

2、列式數(shù)據(jù)源

基于ClickHouse數(shù)據(jù)源,演示案例操作的基本邏輯。這里管理和配置庫表。

核心配置文件

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    # ClickHouse數(shù)據(jù)01
    ch-data01:
      driverClassName: ru.yandex.clickhouse.ClickHouseDriver
      url: jdbc:clickhouse://127.0.0.1:8123/query_data01
      tables: ch_table_01,ch_table_02
    # ClickHouse數(shù)據(jù)02
    ch-data02:
      driverClassName: ru.yandex.clickhouse.ClickHouseDriver
      url: jdbc:clickhouse://127.0.0.1:8123/query_data02
      tables: ch_table_01,ch_table_02

核心配置類

@Component
public class ChSourceConfig {
    public volatile Map<String, String[]> chSourceMap = new HashMap<>();
    public volatile Map<String, Connection> connectionMap = new HashMap<>();
    @Value("${spring.datasource.ch-data01.url}")
    private String dbUrl01;
    @Value("${spring.datasource.ch-data01.tables}")
    private String tables01 ;
    @Value("${spring.datasource.ch-data02.url}")
    private String dbUrl02;
    @Value("${spring.datasource.ch-data02.tables}")
    private String tables02 ;
    @PostConstruct
    public void init (){
        try{
            Connection connection01 = getConnection(dbUrl01);
            if (connection01 != null){
                chSourceMap.put(connection01.getCatalog(),tables01.split(","));
                connectionMap.put(connection01.getCatalog(),connection01);
            }
            Connection connection02 = getConnection(dbUrl02);
            if (connection02 != null){
                chSourceMap.put(connection02.getCatalog(),tables02.split(","));
                connectionMap.put(connection02.getCatalog(),connection02);
            }
        } catch (Exception e){e.printStackTrace();}
    }
    private synchronized Connection getConnection (String jdbcUrl) {
        try {
            DriverManager.setLoginTimeout(10);
            return DriverManager.getConnection(jdbcUrl);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null ;
    }
}

3、基本任務(wù)類

既然基于多線程統(tǒng)計(jì),自然需要一個(gè)線程任務(wù)類,這里演示count統(tǒng)計(jì)模式。輸出單個(gè)線程統(tǒng)計(jì)結(jié)果。

public class CountTask implements Callable<Integer> {
    private Connection connection ;
    private String[] tableArray ;
    public CountTask(Connection connection, String[] tableArray) {
        this.connection = connection;
        this.tableArray = tableArray;
    }
    @Override
    public Integer call() throws Exception {
        Integer taskRes = 0 ;
        if (connection != null){
            Statement stmt = connection.createStatement();
            if (tableArray.length>0){
                for (String table:tableArray){
                    String sql = "SELECT COUNT(*) AS countRes FROM "+table ;
                    ResultSet resultSet = stmt.executeQuery(sql) ;
                    if (resultSet.next()){
                        Integer countRes = resultSet.getInt("countRes") ;
                        taskRes = taskRes + countRes ;
                    }
                }
            }
        }
        return taskRes ;
    }
}

4、線程結(jié)果匯總

這里主要啟動(dòng)線程的執(zhí)行,和最后把每個(gè)線程的處理結(jié)果進(jìn)行匯總。

@RestController
public class ChSourceController {
    @Resource
    private ChSourceConfig chSourceConfig ;
    @GetMapping("/countTable")
    public String countTable (){
        Set<String> keys = chSourceConfig.chSourceMap.keySet() ;
        if (keys.size() > 0){
            ExecutorService executor = Executors.newFixedThreadPool(keys.size());
            List<CountTask> countTasks = new ArrayList<>() ;
            for (String key:keys){
                Connection connection = chSourceConfig.connectionMap.get(key) ;
                String[] tables = chSourceConfig.chSourceMap.get(key) ;
                CountTask countTask = new CountTask(connection,tables) ;
                countTasks.add(countTask) ;
            }
            List<Future<Integer>> countList = Lists.newArrayList();
            try {
                if (countTasks.size() > 0){
                    countList = executor.invokeAll(countTasks) ;
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Integer sumCount = 0 ;
            for (Future<Integer> count : countList){
                try {
                    Integer countRes = count.get();
                    sumCount = sumCount + countRes ;
                } catch (Exception e) {e.printStackTrace();}
            }
            return "sumCount="+sumCount ;
        }
        return "No Result" ;
    }
}

5、最后總結(jié)

關(guān)系型分庫,還是列式統(tǒng)計(jì),都是基于特定策略把數(shù)據(jù)分開,然后路由找到數(shù)據(jù),執(zhí)行操作,或者合并數(shù)據(jù),或者直接返回?cái)?shù)據(jù)。

四、源代碼地址

GitHub·地址
https://github.com/cicadasmile/data-manage-parent
GitEE·地址
https://gitee.com/cicadasmile/data-manage-parent

推薦閱讀:數(shù)據(jù)管理

序號(hào)標(biāo)題
01數(shù)據(jù)源管理:主從庫動(dòng)態(tài)路由,AOP模式讀寫分離
02數(shù)據(jù)源管理:基于JDBC模式,適配和管理動(dòng)態(tài)數(shù)據(jù)源
03數(shù)據(jù)源管理:動(dòng)態(tài)權(quán)限校驗(yàn),表結(jié)構(gòu)和數(shù)據(jù)遷移流程

關(guān)于MySQL中數(shù)據(jù)源管理和關(guān)系型分庫分表以及列式庫分布式計(jì)算分別指的是什么就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI