dataX中CommonRdbms的分片過(guò)程

CommonRdbms主要泛指一些常用的傳統(tǒng)數(shù)據(jù)庫(kù)如Mysql、Oracle等,本文以Mysql到Mysql的導(dǎo)入為例說(shuō)明這類(lèi)數(shù)據(jù)庫(kù)的分片過(guò)程。
split的入口是在JobContainer#split,主要包含以下幾個(gè)步驟:

  1. 根據(jù)用戶(hù)配置的值算出當(dāng)前job的channel的建議值;
  2. Reader端分片;
  3. Writer端分片;
  4. 合并Reader和Writer端的分片,一形成一一對(duì)應(yīng)的關(guān)系,便于后面任務(wù)調(diào)度的操作。
// JobContainer#split
private int split() {
        this.adjustChannelNumber();

        if (this.needChannelNumber <= 0) {
            this.needChannelNumber = 1;
        }

        List<Configuration> readerTaskConfigs = this
                .doReaderSplit(this.needChannelNumber);
        int taskNumber = readerTaskConfigs.size();
        List<Configuration> writerTaskConfigs = this
                .doWriterSplit(taskNumber);

        List<Configuration> transformerList = this.configuration.getListConfiguration(CoreConstant.DATAX_JOB_CONTENT_TRANSFORMER);

        LOG.debug("transformer configuration: "+ JSON.toJSONString(transformerList));
        /**
         * 輸入是reader和writer的parameter list,輸出是content下面元素的list
         */
        List<Configuration> contentConfig = mergeReaderAndWriterTaskConfigs(
                readerTaskConfigs, writerTaskConfigs, transformerList);


        LOG.debug("contentConfig configuration: "+ JSON.toJSONString(contentConfig));

        this.configuration.set(CoreConstant.DATAX_JOB_CONTENT, contentConfig);

        return contentConfig.size();
    }

計(jì)算當(dāng)前job的channel的建議值

dataX提供了流量控制,流量控制的主要配置在channel中,先明確幾個(gè)配置:

  • job.setting.speed.channel 用戶(hù)配置的該job所需要的channel的個(gè)數(shù);
  • job.setting.speed.byte 用戶(hù)配置的該job最大的流量
  • core.transport.channel.speed.byte 單個(gè)channel容納最多的字節(jié)數(shù)
  • job.setting.speed.record 用戶(hù)配置該job最大的record流量
  • core.transport.channel.speed.record 單個(gè)channel容納最多的record數(shù)(一個(gè)record可以包含表中的多行數(shù)據(jù))
    上述以core打頭的配置,在$datax_home/conf/core.json中的默認(rèn)配置為-1,即默認(rèn)沒(méi)有配置.如果用戶(hù)需要做流量控制,配置了job.setting.speed.byte就必須配置core.transport.channel.speed.byte;配置了job.setting.speed.record也必須配置core.transport.channel.speed.record,否則會(huì)拋出異常。

當(dāng)前job的channel的建議值計(jì)算過(guò)程是:

  • 如果用戶(hù)做了字節(jié)流量控制,變量needChannelNumberByByte = job總字節(jié)流量/單個(gè)channel的字節(jié)流量;
  • 如果用戶(hù)做了record配置,變量needChannelNumberByRecord = job總reocrd/單個(gè)channel的record;
  • 取min(needChannelNumberByByte, needChannelNumberByRecord)作為返回值。
  • 如果上述兩個(gè)變量的沒(méi)有配置,那么返回用戶(hù)配置的job.setting.speed.channel
    代碼主要在JobContainer#adjustChannelNumber,代碼太長(zhǎng)就不貼代碼了。

Reader端分片

Reader端分片主要是確定Task的數(shù)量,一個(gè)分片對(duì)應(yīng)一個(gè)Task,Writer端的分片數(shù)和Reader一樣,做到一一對(duì)應(yīng)。
Reader端分片的主要邏輯是在ReaderSplitUtil.doSplit(originalConfig, adviceNumber)這個(gè)方法中,其中第一個(gè)參數(shù)是已經(jīng)解析好的Reader端配置,第二個(gè)參數(shù)是第一步算好的channel建議數(shù)。看源碼這個(gè)adviceNumber并沒(méi)有起到很好的作用,因?yàn)閍dviceNumber和表不可能整除另外只有一個(gè)表的時(shí)候,源碼不知道是做了什么騷操作。。。咱也不知道。

  1. 如果是querySQL模式,這個(gè)時(shí)候分片數(shù)不用算了,有幾個(gè)sql就是幾個(gè)分片了,直接返回配置即可。
  2. 如果是table模式并且設(shè)置了splitPk,按照下面的邏輯對(duì)每個(gè)table(可以配置多個(gè)table)進(jìn)行分片。
  • 具體邏輯是在SingleTableSplitUtil#splitSingleTable中;
  • 每個(gè)分片對(duì)應(yīng)一個(gè)Configuration,作為后續(xù)執(zhí)行一個(gè)Task的配置;
  • 獲取splitPk字段在該表中最小值和最大值,如果最大值或者最小值是null直接作為一個(gè)分片返回;
  • 將minPK和maxPK之間的數(shù)據(jù)分成adviceNum等分,如果不能整除則分成adviceNum+1;
  • 按照用戶(hù)的設(shè)置的column和where語(yǔ)句拼接查詢(xún)語(yǔ)句(和querySql中用戶(hù)配置的sql一樣),取上一步每分?jǐn)?shù)據(jù)的minPK和maxPK,并生成where子句拼接到sql上;
  • splitPK字段值為null的將會(huì)作為一分片;
  • 將生成的sql以"querySql"作為鍵設(shè)置進(jìn)configuration中,一個(gè)分片就此完成。

注意Reader端是可以配置多個(gè)connection元素的,每個(gè)connection中的每張表分片的處理邏輯是一樣的,并且最后返回的configuration中已經(jīng)包含了該connection的連接信息,最后執(zhí)行導(dǎo)入任務(wù)的時(shí)候只需根據(jù)該分片的連接信息執(zhí)行querySql即可。

Writer端的分片

Writer端分片的邏輯是在WriterUtil#doSplit (Configuration simplifiedConf,int adviceNumber)這個(gè)方法中,其中第一個(gè)參數(shù)是已經(jīng)解析好的Writer端配置,第二個(gè)參數(shù)是Reader分片算好的建議分片數(shù),這個(gè)不應(yīng)該叫建議數(shù)了因?yàn)閃riter端一定會(huì)按照這個(gè)數(shù)進(jìn)行分片,以做到Reader端和Writer端的一一對(duì)應(yīng)。
具體操作為:

  • 如果將所有數(shù)據(jù)導(dǎo)入到一張表中,那么Reader端有幾個(gè)分片就返回幾個(gè)configuration,configuration主要包括連接信息、表名、字段等信息;
  • 如果Writer端配置了多個(gè)connection和多個(gè)table(如果adviceNumber和配置的表的個(gè)數(shù)不一樣直接拋出異常),則會(huì)安裝這些在配置文件出場(chǎng)的先后順序解析成configuration并返回。

合并Reader和Writer端的分片

將Reader端和Writer端返回的configuration按照一一對(duì)應(yīng)的順序封裝進(jìn)一個(gè)新的配置中,便于后續(xù)的執(zhí)行。

一個(gè)栗子

這個(gè)栗子主要說(shuō)明多個(gè)分片,Reader端和Writer端一一對(duì)應(yīng)的關(guān)系。下面配置文件中直接用querySql模式配置了3個(gè)分片,Writer端配置了多個(gè)connection和多張表,左后執(zhí)行的結(jié)果為:

  • select* from user where id = 1這條sql查詢(xún)出來(lái)的數(shù)據(jù)會(huì)導(dǎo)入到表user1中;
  • select* from user where id = 2這條sql查詢(xún)出來(lái)的數(shù)據(jù)會(huì)導(dǎo)入到表user2中;
  • select* from user where id = 3這條sql查詢(xún)出來(lái)的數(shù)據(jù)會(huì)導(dǎo)入到表user3中;
"job": {
        "setting": {
            "speed": {
                 "channel": 10
            },
            "errorLimit": {
                "record": 0,
                "percentage": 0.02
            }
        },
        "content": [
            {
                "reader": {
                    "name": "mysqlreader",
                    "parameter": {
                        "username": "root",
                        "password": "123456",
                        "column": ["*"],
                        "connection": [
                            {
                                "querySql": ["select* from user where id = 1",
                                             "select* from user where id = 2",
                                             "select* from user where id = 3",
                                            ],
                                "jdbcUrl": ["jdbc:mysql://172.10.10.231:3306/test"]
                            }
                        ]
                    }
                },
               "writer": {
                    "name": "mysqlwriter",
                    "parameter": {
                        "writeMode": "insert",
                        "username": "root",
                        "password": "123456",
                        "column": ["*"],
                        "connection": [
                            {
                                "jdbcUrl": "jdbc:mysql://172.10.10.231:3306/test1",
                                "table": [
                                    "user1",
                                    "user2"
                                ]
                            },
                            {
                                "jdbcUrl": "jdbc:mysql://172.10.10.231:3306/test2",
                                "table": [
                                    "user3"
                                ]
                            }
                        ]
                    }
                }
            }
        ]
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,460評(píng)論 6 538
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,067評(píng)論 3 423
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 177,467評(píng)論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 63,468評(píng)論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,184評(píng)論 6 410
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 55,582評(píng)論 1 325
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,616評(píng)論 3 444
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 42,794評(píng)論 0 289
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,343評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,096評(píng)論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,291評(píng)論 1 371
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,863評(píng)論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,513評(píng)論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 34,941評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 36,190評(píng)論 1 291
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,026評(píng)論 3 396
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,253評(píng)論 2 375