DBA 小記 — 分庫分表、主從、讀寫分離

来源:https://www.cnblogs.com/jett010/archive/2018/04/12/8807563.html
-Advertisement-
Play Games

前言 我在上篇博客 “Spring Boot 的實踐與思考” 中比對不同規範的 ORM 框架應用場景的時候提到過主從與讀寫分離,本篇隨筆將針對此和分庫分表進行更深入地探討。 1. 漫談 在進入正題之前,我想先隨意談談對架構的拓展周期的想法(僅個人觀點)。首先,我認為初期規劃不該太複雜或者龐大,無論項 ...


前言

我在上篇博客 “Spring Boot 的實踐與思考” 中比對不同規範的 ORM 框架應用場景的時候提到過主從與讀寫分離,本篇隨筆將針對此和分庫分表進行更深入地探討。

1. 漫談

在進入正題之前,我想先隨意談談對架構的拓展周期的想法(僅個人觀點)。首先,我認為初期規劃不該太複雜或者龐大,無論項目的中長期可能會發展地如何如何,前期都應該以靈活為優先,像分庫分表等操作不應該在開始的時候就考慮進去。其次,我認為需求變更是非常正常的,這點在我等開發的圈子裡吐槽的最多,其中自然有 “領導們” 在業務方面欠缺整體考慮的因素,但我們也不該局限在一個觀點內,市場中變則通,不變則死,前期更是如此,因此在前幾版的架構中我們必須要考慮較高的可擴展性。最後,當項目經過幾輪市場的洗禮和迭代開發,核心業務趨於穩定了,此時我們再結合中長期的規劃給系統來一次重構,細緻地去劃分領域邊界,該解耦的解耦,該拆分的拆分。

2. 分庫分表

2.1 概述

當資料庫達到一定規模後(比如說大幾千萬以上),切分是必須要考慮的。一般來說我們首先要進行垂直切分,即按業務分割,比如說用戶相關、訂單相關、統計相關等等都可以單獨成庫。圖片來源 →

但僅僅如此這是完全不夠的,垂直切分雖然剝離了一定的數據,但每個業務還是那個數量級,因此我們還得採取水平切分進一步分散數據,這也是本節論述的重點。

分庫分表的優點相信上述兩圖都一目瞭然了,一個是專庫專用,業務更集中,另一個是提升資料庫服務的負載能力。But there are always two sides to a coin。 從此以後你要接受你的系統複雜度將提升一個檔次,迭代、遷移、運維等都不再容易。

2.2 切分策略

垂直切分在實現上就是一個多數據源的問題,沒啥好講的。以下 Demo 為水平切分,基於 Sharding-JDBC 中間件,我只做邏輯上的陳述,有關其更詳細的信息和配置請移步 “官方文檔”。

首先,我們得在配置文件中定義分片策略,application.yml:

server:
  port: 8001
  
mybatis:
  config-location: classpath:mybatis/mybatis-config.xml
  mapper-locations: classpath:mybatis/mappers/*.xml

sharding:
  jdbc:
    datasource:
      names: youclk_0,youclk_1
      youclk_0:
        type: org.apache.commons.dbcp.BasicDataSource
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://mysql:3306/youclk_0?useSSL=false
        username: root
        password: youclk
      youclk_1:
        type: org.apache.commons.dbcp.BasicDataSource
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://mysql:3306/youclk_1?useSSL=false
        username: root
        password: youclk
    config:
      sharding:
        default-database-strategy:
          inline:
            sharding-column: number
            algorithm-expression: youclk_${number % 2}
        tables:
          user:
            actual-data-nodes: youclk_${0..1}.user

具體每個參數的含義在官方文檔有詳細解釋,其實看名稱也能理解個大概了,我定義將 number 為偶數的數據存入 youclk_0,奇數存入 youclk_1。

User:

@Data
public class User {
    private String id;
    private Integer number;
    private Date createTime;
}

UserRepository:

@Mapper
public interface UserRepository {
    void insert(User user);
}

UserMapper.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.youclk.data.repository.UserRepository">
    <resultMap id="BaseResultMap" type="com.youclk.data.entity.User">
        <id column="id" property="id" jdbcType="CHAR"/>
        <result column="number" property="number" jdbcType="INTEGER"/>
        <result column="createTime" property="create_time" jdbcType="DATE"/>
    </resultMap>

    <sql id="Base_Column_List">
        id, number, createTime
    </sql>
    
    <insert id="insert">
        INSERT INTO user (
          id, number
        )
        VALUES (
            uuid(),
            #{number,jdbcType=INTEGER}
        )
    </insert>
</mapper>

UserService:

@Service
public class UserService {

    @Resource
    private UserRepository userRepository;

    public void insert() {
        for (int i = 0; i < 10; i++) {
            User user = new User();
            user.setNumber(i);
            userRepository.insert(user);
        }
    }
}

Result:

以上做了一個簡單的迴圈插入,可以看到數據已經按策略分庫存儲,結果符合我們的預期。

分庫之後在查詢方面要比之前更加謹慎,既然按策略去切了,那最好就是按策略去查,否則...比如我水平切分了 100個庫,若不按策略去查詢 LIMIT 100000, 10 這麼一組數據,那最後掃描的數量級別是 100 * (100000 + 10), 這是比較恐怖的,雖然 Sharding-JDBC 做了一些優化,比如他不是一次性去查詢到記憶體中,而是採用流式處理 + 歸併排序的方式,但仍然比較耗資源,能避免還是儘量去避免吧。

2.3 分散式事務

在任何系統中事務都是頂要緊的事情,面對已分庫的系統更是如此,保證誇庫事務的安全從來不容易。分散式事務的場景有兩種,一個是在分散式服務中,這個後續有機會再探討,本節重點關註誇庫事務。

Sharding-JDBC 自動包含了弱XA事務支持,即能夠保證邏輯上的事務安全,但因網路或硬體導致的異常無法回滾,實現上與一般事務無異:

@Test
@Transactional
public void insertTest() {
    userService.insert();
    int error = Integer.parseInt("I want error");
    userService.insert();
}

可以看到誇庫事務已回滾,除此之外 Sharding-JDBC 還提供了最大努力送達型柔性事務(將執行過程記錄到日誌中,失敗重試,成功後刪除,若最終還是失敗則保留事務日誌,供人工干預),雖然安全性更高,但無法保證時效,限制也很多,這裡留個待續吧,後續有空再深入探討(主要是比較晚了,想早點寫完休息

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • $(filter pattern…,text) Returns all whitespace separated words in text that do match any of the pattern words, removing any words that do not match. T ...
  • 背景 本學期在北京大學選修了《資料庫概論》的實驗班課程,由於 SQL 語法並不是特別理論的內容,因此課上暫時也沒有特別展開。出於探索資料庫領域的興趣,使用國內普遍使用的資料庫軟體 MySQL 實踐《資料庫系統概念》中若幹 SQL 語句主題;出於方便描述考慮,主要使用命令行界面操作。 MySQL 的安 ...
  • 最近有次在修改某段程式時,發現一段程式演算法看起來簡單。 但背後因為多次查詢數據庫,導致效能問題。 這段程式主要是利用 EPPLUS 讀取 Excel 資料,檢查資料是否已存在數據庫中,若有就將已存在的序號回傳 優化前的案例原碼如下 從上述可以看到,對於每一行Row的資料,都進一次庫去做查詢比對 那在 ...
  • 今天遇到一起關於分散式事務錯誤的案例,如下所示,執行SQL腳本時報錯, 錯誤信息具體如下所示: [OLE/DB provider returned message: 新事務不能登記到指定的事務處理器中。 ] OLE DB error trace [OLE/DB Provider 'SQLOLEDB'... ...
  • 面試碰到一個MySQl的有趣的題目,如何從student表中刪除重覆名字的行,並保留最小id的記錄? 很遺憾當時沒有做出來,回家搜索了一番,發現利用子查詢的可以很快解決。 1、刪除表中多餘的重覆記錄,重覆記錄是username判斷,只留有id最小的記錄 (上面這條語句在mysql中執行會報錯: 執行 ...
  • 預設情況下,mysql.db表中包含的行表示任意用戶可以訪問test資料庫和test_開頭的資料庫。這些行的User欄位的值為空,表示匹配任意用戶。這意味著這些資料庫(test資料庫和test_開頭的資料庫)預設可以被任意用戶使用(即使沒有許可權的用戶)。 mysql.db 預設設置: 初始化的mys ...
  • 最近在部署Zabbix時需要用腳本取得一些MySQL的返回參數,需要是numberic格式的,但是調用腳本時總是輸出這一句: grep -v也是處理不掉的,很是煩人,在網上翻了翻解決掉,記錄於此: Mysql命令有個如下參數: 因此編輯一個password.txt的文件: 腳本中的MySQL連接使用 ...
  • 這裡要分享的HanLP是我在學習使用大快DKhadoop大數據一體化平臺時使用到的自然語言處理技術,使用這個組建可以很高效的進行自然語言的處理工作,比如進行文章摘要,語義判別以及提高內容檢索的精確度和有效性等。 本想找個通俗的案例來介紹一下HanLP,一時間也沒想到什麼好的案例,索性就從HanLp... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...