淺談分庫分表那些事兒

簡介:本文主要闡述在分庫分表改造過程中需要考慮的因素以及對應(yīng)的解法宪巨,還有踩過的那些坑糙麦。

本文適合閱讀群眾:需要從單庫單表改造為多庫多表的新手妇蛀。

本文主要闡述在分庫分表改造過程中需要考慮的因素以及對應(yīng)的解法主届,還有踩過的那些坑脆霎。

前言

我們既然要做分庫分表另锋,那總要有個做事的動機滞项。那么,在動手之前夭坪,首先就要弄明白下面兩個問題文判。

什么是分庫分表?

其實就是字面意思室梅,很好理解:

分庫:從單個數(shù)據(jù)庫拆分成多個數(shù)據(jù)庫的過程戏仓,將數(shù)據(jù)散落在多個數(shù)據(jù)庫中。
分表:從單張表拆分成多張表的過程亡鼠,將數(shù)據(jù)散落在多張表內(nèi)赏殃。

為什么要分庫分表?

關(guān)鍵字:提升性能间涵、增加可用性仁热。

從性能上看

隨著單庫中的數(shù)據(jù)量越來越大、數(shù)據(jù)庫的查詢QPS越來越高勾哩,相應(yīng)的股耽,對數(shù)據(jù)庫的讀寫所需要的時間也越來越多根盒。數(shù)據(jù)庫的讀寫性能可能會成為業(yè)務(wù)發(fā)展的瓶頸。對應(yīng)的物蝙,就需要做數(shù)據(jù)庫性能方面的優(yōu)化。本文中我們只討論數(shù)據(jù)庫層面的優(yōu)化敢艰,不討論緩存等應(yīng)用層優(yōu)化的手段诬乞。

如果數(shù)據(jù)庫的查詢QPS過高,就需要考慮拆庫钠导,通過分庫來分擔(dān)單個數(shù)據(jù)庫的連接壓力震嫉。比如,如果查詢QPS為3500牡属,假設(shè)單庫可以支撐1000個連接數(shù)的話票堵,那么就可以考慮拆分成4個庫,來分散查詢連接壓力逮栅。

如果單表數(shù)據(jù)量過大悴势,當(dāng)數(shù)據(jù)量超過一定量級后,無論是對于數(shù)據(jù)查詢還是數(shù)據(jù)更新措伐,在經(jīng)過索引優(yōu)化等純數(shù)據(jù)庫層面的傳統(tǒng)優(yōu)化手段之后特纤,還是可能存在性能問題。這是量變產(chǎn)生了質(zhì)變侥加,這時候就需要去換個思路來解決問題捧存,比如:從數(shù)據(jù)生產(chǎn)源頭、數(shù)據(jù)處理源頭來解決問題担败,既然數(shù)據(jù)量很大昔穴,那我們就來個分而治之,化整為零提前。這就產(chǎn)生了分表吗货,把數(shù)據(jù)按照一定的規(guī)則拆分成多張表,來解決單表環(huán)境下無法解決的存取性能問題岖研。

從可用性上看

單個數(shù)據(jù)庫如果發(fā)生意外卿操,很可能會丟失所有數(shù)據(jù)。尤其是云時代孙援,很多數(shù)據(jù)庫都跑在虛擬機上害淤,如果虛擬機/宿主機發(fā)生意外,則可能造成無法挽回的損失拓售。因此窥摄,除了傳統(tǒng)的 Master-Slave、Master-Master 等部署層面解決可靠性問題外础淤,我們也可以考慮從數(shù)據(jù)拆分層面解決此問題崭放。

此處我們以數(shù)據(jù)庫宕機為例:

  • 單庫部署情況下哨苛,如果數(shù)據(jù)庫宕機,那么故障影響就是100%币砂,而且恢復(fù)可能耗時很長建峭。
  • 如果我們拆分成2個庫,分別部署在不同的機器上决摧,此時其中1個庫宕機亿蒸,那么故障影響就是50%,還有50%的數(shù)據(jù)可以繼續(xù)服務(wù)掌桩。
  • 如果我們拆分成4個庫边锁,分別部署在不同的機器上,此時其中1個庫宕機波岛,那么故障影響就是25%茅坛,還有75%的數(shù)據(jù)可以繼續(xù)服務(wù),恢復(fù)耗時也會很短则拷。
    當(dāng)然贡蓖,我們也不能無限制的拆庫,這也是犧牲存儲資源來提升性能隔躲、可用性的方式摩梧,畢竟資源總是有限的。

如何分庫分表

分庫宣旱?分表仅父?還是既分庫又分表?

從第一部分了解到的信息來看浑吟,分庫分表方案可以分為下面3種:


如何選擇我們自己的切分方案笙纤?

如果需要分表,那么分多少張表合適组力?
由于所有的技術(shù)都是為業(yè)務(wù)服務(wù)的省容,那么,我們就先從數(shù)據(jù)方面回顧下業(yè)務(wù)背景燎字。

比如腥椒,我們這個業(yè)務(wù)系統(tǒng)是為了解決會員的咨詢訴求,通過我們的XSpace客服平臺系統(tǒng)來服務(wù)會員候衍,目前主要以同步的離線工單數(shù)據(jù)作為我們的數(shù)據(jù)源來構(gòu)建自己的數(shù)據(jù)笼蛛。

假設(shè),每一筆離線工單都會產(chǎn)生對應(yīng)一筆會員的咨詢問題(我們簡稱:問題單)蛉鹿,如果:

  • 在線渠道:每天產(chǎn)生 3w 筆聊天會話滨砍,假設(shè),其中50%的會話會生成一筆離線工單,那么每天可生成 3w * 50% = 1.5w 筆工單惋戏;
  • 熱線渠道:每天產(chǎn)生 2.5w 通電話领追,假設(shè),其中80%的電話都會產(chǎn)生一筆工單响逢,那么每天可生成 2.5w * 80% = 2w 筆/天绒窑;
  • 離線渠道:假設(shè)離線渠道每天直接生成 3w 筆;
    合計共 1.5w + 2w + 3w = 6.5w 筆/天

考慮到以后可能要繼續(xù)覆蓋的新的業(yè)務(wù)場景舔亭,需要提前預(yù)留部分?jǐn)U展空間回论,這里我們假設(shè)為每天產(chǎn)生 8w 筆問題單。

除問題單外分歇,還有另外2張常用的業(yè)務(wù)表:用戶操作日志表、用戶提交的表單數(shù)據(jù)表欧漱。

其中职抡,每筆問題單都會產(chǎn)生多條用戶操作日志,根據(jù)歷史統(tǒng)計數(shù)據(jù)來可以看到误甚,平均每個問題單大約會產(chǎn)生8條操作日志缚甩,我們預(yù)留一部分空間,假設(shè)每個問題單平均產(chǎn)生約10條用戶操作日志窑邦。

如果系統(tǒng)設(shè)計使用年限5年擅威,那么問題單數(shù)據(jù)量大約 = 5年 365天/年 8w/天 = 1.46億,那么估算出的表數(shù)量如下:

  • 問題單需要:1.46億/500w = 29.2 張表冈钦,我們就按 32 張表來切分郊丛;
  • 操作日志需要 :32 10 = 320 張表,我們就按 32 16 = 512 張表來切分瞧筛。
    如果需要分庫厉熟,那么分多少庫合適?
    分庫的時候除了要考慮平時的業(yè)務(wù)峰值讀寫QPS外较幌,還要考慮到諸如雙11大促期間可能達(dá)到的峰值揍瑟,需要提前做好預(yù)估。

根據(jù)我們的實際業(yè)務(wù)場景乍炉,問題單的數(shù)據(jù)查詢來源主要來自于阿里客服小蜜首頁绢片。因此,可以根據(jù)歷史QPS岛琼、RT等數(shù)據(jù)評估底循,假設(shè)我們只需要3500數(shù)據(jù)庫連接數(shù),如果單庫可以承擔(dān)最高1000個數(shù)據(jù)庫連接衷恭,那么我們就可以拆分成4個庫亚斋。

如何對數(shù)據(jù)進(jìn)行切分?

根據(jù)行業(yè)慣例牧抵,通常按照 水平切分、垂直切分 兩種方式進(jìn)行切分猬错,當(dāng)然,有些復(fù)雜業(yè)務(wù)場景也可能選擇兩者結(jié)合的方式茸歧。

(1)水平切分

這是一種橫向按業(yè)務(wù)維度切分的方式倦炒,比如常見的按會員維度切分,根據(jù)一定的規(guī)則把不同的會員相關(guān)的數(shù)據(jù)散落在不同的庫表中软瞎。由于我們的業(yè)務(wù)場景決定都是從會員視角進(jìn)行數(shù)據(jù)讀寫逢唤,所以,我們就選擇按照水平方式進(jìn)行數(shù)據(jù)庫切分涤浇。

(2)垂直切分

垂直切分可以簡單理解為鳖藕,把一張表的不同字段拆分到不同的表中。

比如:假設(shè)有個小型電商業(yè)務(wù)只锭,把一個訂單相關(guān)的商品信息著恩、買賣家信息、支付信息都放在一張大表里蜻展『硖埽可以考慮通過垂直切分的方式,把商品信息纵顾、買家信息伍茄、賣家信息、支付信息都單獨拆分成獨立的表施逾,并通過訂單號跟訂單基本信息關(guān)聯(lián)起來敷矫。

也有一種情況,如果一張表有10個字段音念,其中只有3個字段需要頻繁修改沪饺,那么就可以考慮把這3個字段拆分到子表。避免在修改這3個數(shù)據(jù)時闷愤,影響到其余7個字段的查詢行鎖定整葡。

分庫分表之后帶來的新問題

分庫分表后,如何讓數(shù)據(jù)均勻散落在各個分庫分表內(nèi)讥脐?

比如遭居,當(dāng)熱點事件出現(xiàn)后,怎么避免熱點數(shù)據(jù)集中存取到某個特定庫/表旬渠,造成各分庫分表讀寫壓力不均的問題俱萍。

其實,細(xì)思之下可以發(fā)現(xiàn)這個問題其實跟負(fù)載均衡的問題很相似告丢,所以枪蘑,我們可以去借鑒下負(fù)載均衡的解法來解決。我們常見的負(fù)責(zé)均衡算法如下:


我們的選擇:基于 一致性Hash算法 裁剪,相較于一致性Hash算法岳颇,我們裁剪后的算法
主要區(qū)別在以下幾個點:

(1)Hash環(huán)節(jié)點數(shù)量的不同

一致性Hash有2^32-1個節(jié)點照捡,考慮到我們按照buyerId切分,而且buyerId基數(shù)本就很龐大话侧,整體已經(jīng)具備一定的均勻度栗精,所以,我們把Hash環(huán)的數(shù)量降低到4096個瞻鹏;

(2)DB索引算法的不同

一致性Hash通過類似 hash(DB的IP) % 2^32 公式計算DB在Hash環(huán)的位置悲立。如果DB數(shù)量較少,需要通過增加虛擬節(jié)點來解決Hash環(huán)偏斜問題新博,而且DB的位置可能會隨著IP的變動而變化薪夕,尤其是在云環(huán)境下。

數(shù)據(jù)均勻分布到Hash環(huán)的問題赫悄,經(jīng)過之前的判斷寥殖,我們可以通過 Math.abs(buyerId.hashCode()) % 4096 計算定位到Hash環(huán)位置,那么剩下的問題就是讓DB也均勻分布到這個Hash環(huán)上即可涩蜘。由于我們都是使用阿里的TDDL中間件,只需要通過邏輯上的分庫索引號定位DB熏纯,因此同诫,我們把分庫DB均分到這個Hash環(huán)上即可,如果是hash環(huán)有4096個環(huán)節(jié)樟澜,拆分4庫的話误窖,那么4個庫分別位于第1、1025秩贰、2049霹俺、3073個節(jié)點上。分庫的索引定位可通過 (Math.abs(buyerId.hashCode()) % 4096) / (4096 / DB_COUNT) 這個公式計算得出毒费。

分庫索引的 Java 偽代碼實現(xiàn)如下:

/**
 * 分庫數(shù)量
 */
public static final int DB_COUNT = 4;

/**
 * 獲取數(shù)據(jù)庫分庫索引號
 *
 * @param buyerId 會員ID
 * @return
 */
public static int indexDbByBuyerId(Long buyerId) {
    return (Math.abs(buyerId.hashCode()) % 4096) / (4096 / DB_COUNT);
}

分庫分表環(huán)境下丙唧,如何解決分庫后主鍵ID的唯一性問題?

在單庫環(huán)境下觅玻,我們的問題單主表的ID采用的MySQL自增的方式想际。但是,分庫之后如果還繼續(xù)使用數(shù)據(jù)庫自增的方式溪厘,就很容易出現(xiàn)各門口的主鍵ID重復(fù)問題胡本。

對于這種情況,有很多種解決方案畸悬,比如采用UUID的方式侧甫,不過UUID太長,查詢性能太差,占用空間也大披粟,而且主鍵的類型也變了咒锻,也不利于應(yīng)用平滑遷移。

其實僻爽,我們也可以對ID繼續(xù)拆分虫碉,比如對ID進(jìn)行分段,不同的庫表使用不同的ID段胸梆,但也會產(chǎn)生新的問題敦捧,這個ID段要多長才合適?如果ID段分配完了碰镜,那可能會占用第二個庫的ID段兢卵,產(chǎn)生ID不唯一問題。

但是绪颖,如果我們讓所有的分庫使用的ID段按照等差數(shù)列進(jìn)行分隔秽荤,每次ID段用完之后,再按照固定的步長比遞增的話柠横,那是不是就可以解決這個問題了窃款。

比如,像下面這樣牍氛,假設(shè)每次分配的ID間隔為1000晨继,也就是步長1000,那么每次分配的ID段起止索引則可以按照下面的公式計算得出:

  • 第X庫搬俊、第Y次分配的ID段起始索引就是:

X * 步長 + (Y-1) * (庫數(shù)量 * 步長)

  • 第X庫紊扬、第Y次分配的ID段結(jié)束索引就是:

X * 步長 + (Y-1) * (庫數(shù)量 * 步長) + (1000 -1)

如果是分4庫,那么最終分配的ID段就會是下面這個樣子:


我們的問題單庫采用的就是這種先對ID分段唉擂,再按固定步長遞增的方式餐屎。這也是TDDL官方提供的解決方案。

除此之外玩祟,實際場景下腹缩,通常為了分析排查問題方便,往往會在ID中增加一些額外信息空扎,比如我們自己的問題單ID就包含了日期庆聘、版本、分庫索引等信息勺卢。

問題單 ID 生成 Java 偽代碼參考:

import lombok.Setter;
import org.apache.commons.lang3.time.DateFormatUtils;

/**
 * 問題單ID構(gòu)建器
 * <p>
 * ID格式(18位):6位日期 + 2位版本號 + 2位庫索引號 + 8位序列號
 * 示例:180903010300001111
 * 說明這個問題單是2018年9月3號生成的伙判,采用的01版本的ID生成規(guī)則,數(shù)據(jù)存放在03庫黑忱,最后8位00001111是生成的序列號ID宴抚。* 采用這種ID格式還有個好處就是每天都有1億(8位)的序列號可用勒魔。* </p>
 */
@Setter
public class ProblemOrdIdBuilder {
  public static final int DB_COUNT = 4;    
    private static final String DATE_FORMATTER = "yyMMdd";

    private String version = "01";
    private long buyerId;
    private long timeInMills;
    private long seqNum;

    public Long build() {
        int dbIndex = indexDbByBuyerId(buyerId);
        StringBuilder pid = new StringBuilder(18)
            .append(DateFormatUtils.format(timeInMills, DATE_FORMATTER))
            .append(version)
            .append(String.format("%02d", dbIndex))
            .append(String.format("%08d", seqNum % 10000000));
        return Long.valueOf(pid.toString());
    }

    /**
     * 獲取數(shù)據(jù)庫分庫索引號
     *
     * @param buyerId 會員ID
     * @return
     */
    public int indexDbByBuyerId(Long buyerId) {
        return (Math.abs(buyerId.hashCode()) % 4096) / (4096 / DB_COUNT);
    }
}

分庫分表環(huán)境下,事務(wù)問題怎么解決菇曲?

由于分布式環(huán)境下冠绢,一個事務(wù)可能跨多個分庫,所以常潮,處理起來相對復(fù)雜弟胀。目前常見的有2種解決方案:

(1)使用分布式事務(wù)

  • 優(yōu)點:由應(yīng)用服務(wù)器/數(shù)據(jù)庫去管理事務(wù),實現(xiàn)簡單
  • 缺點:性能代價較高喊式,尤其是涉及到分庫數(shù)量較多時尤為明顯孵户。而且,還依賴于一些特定的應(yīng)用服務(wù)器/數(shù)據(jù)庫提供的分布式事務(wù)實現(xiàn)方案岔留。
    (2)由應(yīng)用程序+數(shù)據(jù)庫共同控制
  • 原理:大事化小夏哭,將多個大事務(wù)拆分成可由單個分庫處理的小事務(wù),由應(yīng)用程序去控制這些小事務(wù)献联。
  • 優(yōu)點:性能良好竖配,少了一個分布式事務(wù)協(xié)調(diào)處理層
  • 缺點:需要從應(yīng)用程序自身上做事務(wù)控制的靈活設(shè)計。從業(yè)務(wù)應(yīng)用上做處理里逆,應(yīng)該改造成本高进胯。
    針對上面2種分布式事務(wù)解決方案,我們該如何選擇原押?

首先龄减,沒有萬能的解決方案,只有適合自己的方案班眯。那就先看看我們的業(yè)務(wù)中,事務(wù)的使用場景有哪些吧烁巫。

無論是來咨詢問題的會員署隘,還是為會員解決問題的客服小二,亦或者從第三方系統(tǒng)同步相關(guān)數(shù)據(jù)亚隙。主要有2個核心動作:

  • 以會員維度查詢相關(guān)進(jìn)度數(shù)據(jù)磁餐,包含會員問題數(shù)據(jù),以及對應(yīng)的問題處理操作日志/進(jìn)度數(shù)據(jù)阿弃;
  • 以會員視角提交相關(guān)憑證/反饋新情況等數(shù)據(jù)诊霹,或者是客服小二代會員提交這些數(shù)據(jù)。提交的數(shù)據(jù)也可能會決定問題是否解決(被完結(jié))渣淳。
    由于問題單數(shù)據(jù)脾还、操作日志都是分開查詢,所以入愧,不涉及分布式關(guān)聯(lián)查詢場景鄙漏,這個可以忽略不考慮嗤谚。

那么就剩下用戶提交數(shù)據(jù)場景了,可能會同時寫入問題單以及操作日志數(shù)據(jù)怔蚌。

既然使用場景確定了巩步,那么可以選擇事務(wù)解決方案了。雖然分布式事務(wù)實現(xiàn)簡單桦踊,但這個簡單是因為中間件幫我們解決了它本身的復(fù)雜性椅野。復(fù)雜性越高,必然會帶來一定的性能損耗籍胯。而且竟闪,目前大部分應(yīng)用都是基于 SpringBoot 開發(fā),默認(rèn)使用的都是內(nèi)嵌 tomcat 容器芒炼,不像 IBM 提供的 WebSphere Application Server瘫怜、Oracle 的 WebLogic 這些重量級應(yīng)用服務(wù)器,都提供了內(nèi)置的分布式事務(wù)管理器本刽。因此鲸湃,如果我們要接入,必然要自己引入額外的分布式事務(wù)管理器子寓,這個接入成本就更高了暗挑。所以,這種方案就暫不考慮了斜友。那么炸裆,就只能自己想辦法把大事務(wù)切分成單庫可以解決的小事務(wù)了。

所以鲜屏,現(xiàn)在問題就成了烹看,如何讓同一個會員的問題單數(shù)據(jù)和這個問題單相關(guān)的操作日志數(shù)據(jù)寫入到同一個分庫中。其實洛史,解決方案也比較簡單惯殊,由于都是使用會員ID做切分,那么使用相同的分庫路由規(guī)則即可也殖。

最后土思,我來看下最終的 TDDL 分庫分表規(guī)則配置:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
  <bean id="vtabroot" class="com.taobao.tddl.interact.rule.VirtualTableRoot" init-method="init">
    <property name="dbType" value="MYSQL" />
    <property name="defaultDbIndex" value="PROBLEM_0000_GROUP" />
    <property name="tableRules">
      <map>
        <entry key="problem_ord" value-ref="problem_ord" />
        <entry key="problem_operate_log" value-ref="problem_operate_log" />
      </map>
    </property>
  </bean>
  <!-- 問題(訴求)單表 -->
  <bean id="problem_ord" class="com.taobao.tddl.interact.rule.TableRule">
    <property name="dbNamePattern" value="PROBLEM_{0000}_GROUP" />
    <property name="tbNamePattern" value="problem_ord_{0000}" />
    <property name="dbRuleArray" value="((Math.abs(#buyer_id,1,4#.hashCode()) % 4096).intdiv(1024))" />
    <property name="tbRuleArray">
      <list>
        <value>
          <![CDATA[
            def hashCode = Math.abs(#buyer_id,1,32#.hashCode());
            int dbIndex = ((hashCode % 4096).intdiv(1024)) as int;
            int tableCountPerDb = 32 / 4;
            int tableIndexStart = dbIndex * tableCountPerDb;
            int tableIndexOffset = (hashCode % tableCountPerDb) as int;
            int tableIndex = tableIndexStart + tableIndexOffset;
            return tableIndex;
          ]]>
        </value>
      </list>
    </property>
    <property name="allowFullTableScan" value="false" />
  </bean>
  <!-- 問題操作日志表 -->
  <bean id="problem_operate_log" class="com.taobao.tddl.interact.rule.TableRule">
    <property name="dbNamePattern" value="PROBLEM_{0000}_GROUP" />
    <property name="tbNamePattern" value="problem_operate_log_{0000}" />
    <!-- 【#buyer_id,1,4#.hashCode()】 -->
    <!-- buyer_id 代表分片字段;1代表分庫步長忆嗜;4代表一共4個分庫己儒,當(dāng)執(zhí)行全表掃描時會用到 -->
    <property name="dbRuleArray" value="((Math.abs(#buyer_id,1,4#.hashCode()) % 4096).intdiv(1024))" />
    <property name="tbRuleArray">
      <list>
        <value>
          <![CDATA[
            def hashCode = Math.abs(#buyer_id,1,512#.hashCode());
            int dbIndex = ((hashCode % 4096).intdiv(1024)) as int;
            int tableCountPerDb = 512 / 4;
            int tableIndexStart = dbIndex * tableCountPerDb;
            int tableIndexOffset = (hashCode % tableCountPerDb) as int;
            int tableIndex = tableIndexStart + tableIndexOffset;
            return tableIndex;
          ]]>
        </value>
      </list>
    </property>
    <property name="allowFullTableScan" value="false" />
  </bean>
</beans>

分庫分表后,歷史數(shù)據(jù)如何平滑遷移捆毫?

數(shù)據(jù)庫復(fù)制方案闪湾,阿里云上面也開放了以前阿里內(nèi)部使用的數(shù)據(jù)庫復(fù)制、遷移方案《數(shù)據(jù)傳輸服務(wù)(Data Transmission Service)》[1]绩卤,詳情可咨詢阿里云客服或者阿里云數(shù)據(jù)庫專家响谓。

分庫切換發(fā)布流程可選擇停機损合、不停機發(fā)布兩種:

(1)如果選擇停機發(fā)布

  • 首先,要選擇一個夜黑風(fēng)高娘纷、四處無人的夜晚嫁审。寒風(fēng)刺骨能讓你清醒,四處無人赖晶,你好辦事打劫偷數(shù)據(jù)律适,我們就挑了個凌晨4點寂靜無人的時候做切換;如果可以遏插,能臨時關(guān)閉業(yè)務(wù)訪問入口最好捂贿。

  • 然后,在DTS上面新增一個全量的數(shù)據(jù)復(fù)制任務(wù)胳嘲,把單庫的數(shù)據(jù)復(fù)制到新的分庫中(這個過程很快厂僧,千萬級數(shù)據(jù)應(yīng)該10分左右就能搞定);

  • 之后了牛,切換 TDDL 配置(單庫->分庫)颜屠,并重啟應(yīng)用,檢查是否生效鹰祸。

  • 最后甫窟,開放業(yè)務(wù)訪問入口,提供服務(wù)蛙婴。
    (2)如果選擇不停機發(fā)布話粗井,流程會略微復(fù)雜點

  • 首先,同樣需要選擇一個夜黑風(fēng)高的夜晚街图,來襯托你的帥氣浇衬。

  • 然后,通過DTS復(fù)制某個時間點前的數(shù)據(jù)餐济,比如:今天前的歷史數(shù)據(jù)耘擂。

  • 之后,從單庫切換到分庫(最好是提前發(fā)布好應(yīng)用颤介、準(zhǔn)備好配置),這樣切換時只需要幾分鐘重啟生效即可赞赖。在切換到分庫前滚朵,聯(lián)系DBA在切換期間停止老的單庫讀寫。

  • 最后前域,分庫切換完成后辕近,再通過DTS增量復(fù)制老的單庫中今天凌晨之后產(chǎn)生的數(shù)據(jù)。

  • 最后的最后匿垄,持續(xù)觀察一段時間移宅,如果沒問題归粉,老的單庫就可以下線了。

TDDL配置分庫分表路由時的注意事項

由于阿里的TDDL中間件使用groovy腳本計算分庫分表路由漏峰,而 groovy 的 / 運算符 或者 /= 運算符 可能會產(chǎn)生一個 double 類型的結(jié)果糠悼,并非像 Java 那樣得出一個整數(shù),因此需要使用 x.intdiv(y) 函數(shù)做整除運算浅乔。

// 在 Java 中
System.out.println(5 / 3); // 結(jié)果 = 1

// 在 Groovy 中
println (5 / 3);       // 結(jié)果 = 1.6666666667          
println (5.intdiv(3)); // 結(jié)果 = 1(Groovy整除正確用法)

詳情可查看 Groovy 官方說明 《The case of the division operator》:

分庫分表文中案例圖示

參考資料
[1] https://baijiahao.baidu.com/s?id=1622441635115622194&wfr=spider&for=pc
[2] http://www.zsythink.net/archives/1182
[3] https://www.aliyun.com/product/dts
[4] https://docs.groovy-lang.org/latest/html/documentation/core-syntax.html#integer_division
[5] https://github.com/alibaba/tb_tddl

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末倔喂,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子靖苇,更是在濱河造成了極大的恐慌席噩,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件贤壁,死亡現(xiàn)場離奇詭異悼枢,居然都是意外死亡,警方通過查閱死者的電腦和手機脾拆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進(jìn)店門馒索,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人假丧,你說我怎么就攤上這事双揪。” “怎么了包帚?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵渔期,是天一觀的道長。 經(jīng)常有香客問我渴邦,道長疯趟,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任谋梭,我火速辦了婚禮信峻,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘瓮床。我一直安慰自己盹舞,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布隘庄。 她就那樣靜靜地躺著踢步,像睡著了一般。 火紅的嫁衣襯著肌膚如雪丑掺。 梳的紋絲不亂的頭發(fā)上获印,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天,我揣著相機與錄音街州,去河邊找鬼兼丰。 笑死玻孟,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的鳍征。 我是一名探鬼主播黍翎,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蟆技!你這毒婦竟也來了玩敏?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤质礼,失蹤者是張志新(化名)和其女友劉穎旺聚,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體眶蕉,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡砰粹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了造挽。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片碱璃。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖饭入,靈堂內(nèi)的尸體忽然破棺而出嵌器,到底是詐尸還是另有隱情,我是刑警寧澤谐丢,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布爽航,位于F島的核電站,受9級特大地震影響乾忱,放射性物質(zhì)發(fā)生泄漏讥珍。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一窄瘟、第九天 我趴在偏房一處隱蔽的房頂上張望衷佃。 院中可真熱鬧,春花似錦蹄葱、人聲如沸氏义。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽惯悠。三九已至,卻和暖如春琼稻,著一層夾襖步出監(jiān)牢的瞬間吮螺,已是汗流浹背饶囚。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工帕翻, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留鸠补,地道東北人。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓嘀掸,卻偏偏與公主長得像紫岩,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子睬塌,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,843評論 2 354

推薦閱讀更多精彩內(nèi)容