Presto源碼分析之事務(wù)性的數(shù)據(jù)寫入

概述

我們知道事務(wù)性在數(shù)據(jù)處理里面是非常重要的阻星,事務(wù)性決定了你最終數(shù)據(jù)的正確與否挠日。在 OLTP 領(lǐng)域里面事務(wù)一般通過底層存儲提供的事務(wù)機(jī)制就可以搞定了。但是在分布式數(shù)據(jù)處理領(lǐng)域里面赊堪,由于數(shù)據(jù)在被很多節(jié)點(diǎn)同時大規(guī)模分布式地寫祝旷,OLTP 里面的簡單事務(wù)處理就很難處理這種場景了履澳。在 Presto 里面也需要解決這樣的問題,我們今天就來看看 Presto 里面提供了什么樣的機(jī)制來達(dá)到數(shù)據(jù)寫入的事務(wù)性怀跛。

物理執(zhí)行計(jì)劃的基本單元: Operator

在正式介紹數(shù)據(jù)事務(wù)性寫入之前距贷,我們先來看看 Presto 里面物理執(zhí)行計(jì)劃的基本單元: Operator

我們知道在一般的“語言”里面吻谋,把語言從文本編譯到最終可執(zhí)行程序的過程中都會經(jīng)歷從文本到邏輯執(zhí)行計(jì)劃忠蝗,再從邏輯執(zhí)行計(jì)劃到物理執(zhí)行計(jì)劃的編譯過程,Presto 也不例外漓拾,在 Presto 里面邏輯執(zhí)行計(jì)劃是由 PlanNode 組成的阁最, 物理執(zhí)行計(jì)劃則是由 Operator 組成的戒祠。這里先簡單介紹一下 Operator 的設(shè)計(jì)。

語言的編譯過程

下面是 Operator 接口主要方法的定義(為了行文的簡潔性刪除了一些不那么重要的方法):

public interface Operator extends AutoCloseable {
   /**
    * Gets the column types of pages produced by this operator.
    */
   List<Type> getTypes();

   /**
    * Notifies the operator that no more pages will be added and the
    * operator should finish processing and flush results. This method
    * will not be called if the Task is already failed or canceled.
    */
   void finish();

   /**
    * Adds an input page to the operator.  This method will only be called if
    * {@code needsInput()} returns true.
    */
   void addInput(Page page);

   /**
    * Gets an output page from the operator.  If no output data is currently
    * available, return null.
    */
   Page getOutput();
}

這個接口算是 Presto 里面比較良心的接口了, 接口設(shè)計(jì)優(yōu)良速种、每個方法有注釋姜盈、方法的含義也很好理解。

從上述接口定義可以看出 Operator 定義了一個數(shù)據(jù)處理單元配阵,處理的數(shù)據(jù)是 Page , 一批數(shù)據(jù)流進(jìn) Operator 馏颂,經(jīng)過一系列處理邏輯,轉(zhuǎn)換成新的一批數(shù)據(jù)流出到下游別的 Operator 繼續(xù)處理棋傍。

Operator

數(shù)據(jù)處理的粒度是 Page, 但是不是所有的 Page 都一樣救拉,Page 里面的數(shù)據(jù)到底長什么樣是靠 List<Type> getTypes() 這個方法來描述。Operator 通過 addInput 方法接收來自上游的輸入瘫拣,通過 getOuput 把數(shù)據(jù)吐給下游亿絮。

getOutput() 這個方法名字取得很不好,給人的感覺好像是把這個 Operator 的輸出全部拿出來拂铡,它實(shí)際的作用是拿一個 Page 的輸出出來壹无,后面還會有很多輸出,因此我覺得 nextOutput() 可能更表意一點(diǎn)感帅。

Presto 里面的事務(wù)性數(shù)據(jù)寫入

在 Presto 里面我們是可以事務(wù)性地把數(shù)據(jù)插入底層數(shù)據(jù)存儲的 -- 當(dāng)然斗锭,具體的事務(wù)性還是底層存儲而不是 Presto 能夠決定的,但是 Presto 里面提供了相應(yīng)的機(jī)制以使得我們能夠配合底層存儲引擎一起來實(shí)現(xiàn)事務(wù)性的數(shù)據(jù)寫入失球。這個機(jī)制是這樣的:

Presto里面的事務(wù)性數(shù)據(jù)寫入機(jī)制

這個機(jī)制本身其實(shí)不是很復(fù)雜岖是,在寫開始之前給你一個初始化的鉤子(Hook), 然后你分布式地去寫數(shù)據(jù),最后給你一個集中式提交的鉤子(Hook)实苞,有點(diǎn)兩階段提交的意味豺撑。

TableWriterOperator 這個名字起的有問題,對應(yīng)的讀數(shù)據(jù)的 Operator 是 TableScanOperator, 那么這個怎么也應(yīng)該叫 TableWriteOperator 啊黔牵。

上面說的還是太抽象了聪轿,我們來看個具體的例子來看看,怎么通過這個”框架”來實(shí)現(xiàn)事務(wù)性寫數(shù)據(jù)猾浦。這個例子就是 Presto 的 JDBC Connector:

JDBC Connector 在 BeginTableWrite 的時候執(zhí)行了下面這段代碼(BaseJdbcClient#beginWriteTable):

String temporaryName = "tmp_presto_" + 
  UUID.randomUUID().toString().replace("-", "");
StringBuilder sql = new StringBuilder()
   .append("CREATE TABLE ")
   .append(quoted(catalog, schema, temporaryName))
   .append(" (");

ImmutableList.Builder<String> columnList = ImmutableList.builder();
for (ColumnMetadata column : tableMetadata.getColumns()) {
   columnList.add(new StringBuilder()
                  .append(quoted(columnName))
                  .append(" ")
                  .append(toSqlType(column.getType()))
                  .toString());
}

Joiner.on(", ").appendTo(sql, columnList.build());
sql.append(")");
execute(connection, sql.toString());

可以看出這段代碼建了一個臨時表, 在后面的 TableWriterOperator 算子里面陆错,數(shù)據(jù)其實(shí)是在分布式地往這個臨時表里面去寫。

在最后的 TableFinisherOperator 里面執(zhí)行了這么一段代碼(BaseJdbcClient#finishInsertTable):

String temporaryTable = quoted(handle.getCatalogName(), 
  getRealSchemaName(handle), handle.getTemporaryTableName());
String targetTable = quoted(handle.getCatalogName(), 
   getRealSchemaName(handle), getRealTableName(handle));

String insertSql = format("INSERT INTO %s SELECT * FROM %s", 
   targetTable, temporaryTable);
String cleanupSql = "DROP TABLE " + temporaryTable;

execute(connection, insertSql);
execute(connection, cleanupSql);

從代碼可以看出來金赦,JDBC Connector 在最后把數(shù)據(jù)從 temporaryTable 插入到了 targetTable 里面去了音瓷,并且把臨時表 DROP 掉了,由于最后這個操作是事務(wù)性的夹抗,因此保證了整個數(shù)據(jù)寫入的事務(wù)性绳慎。

目前 Presto 的這個方案其實(shí)是有點(diǎn)臟的,細(xì)心的同學(xué)可能已經(jīng)看出來了,上面圖中的 BeginTableWrite 的形狀跟其它節(jié)點(diǎn)的形狀不一樣杏愤。這是因?yàn)?BeginTableWrite 在 Presto 里面不是一個 Operator靡砌。 它甚至不是在任務(wù)的運(yùn)行時執(zhí)行的,而是在編譯期執(zhí)行的(也就是下文中說的 planning)声邦。Presto 的作者在 BeginTableWrite 的文件注釋里面也承認(rèn)了這一點(diǎn)乏奥。

Major HACK alert!!!

This logic should be invoked on query start, not during planning. At that point, the token
returned by beginCreate/beginInsert should be handed down to tasks in a mapping separate
from the plan that links plan nodes to the corresponding token.

總結(jié)

不管怎么樣 Presto 還是能夠支持對數(shù)據(jù)的事務(wù)性插入,雖然方法有點(diǎn)Hack亥曹。從這一點(diǎn)也可以看出 Presto 對待代碼的態(tài)度是實(shí)用性優(yōu)先,先解決問題再說恨诱,方法好不好媳瞪,是不是最正確的方案,以后再說照宝。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蛇受,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子厕鹃,更是在濱河造成了極大的恐慌兢仰,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件剂碴,死亡現(xiàn)場離奇詭異把将,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)忆矛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進(jìn)店門察蹲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人催训,你說我怎么就攤上這事洽议。” “怎么了漫拭?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵亚兄,是天一觀的道長。 經(jīng)常有香客問我采驻,道長审胚,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任挑宠,我火速辦了婚禮菲盾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘各淀。我一直安慰自己懒鉴,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著临谱,像睡著了一般璃俗。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上悉默,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天城豁,我揣著相機(jī)與錄音,去河邊找鬼抄课。 笑死唱星,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的间聊。 我是一名探鬼主播,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼僵蛛,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了飘言?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后苫拍,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年吏够,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡沉噩,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出畜眨,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布约巷,位于F島的核電站,受9級特大地震影響靖榕,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜星压,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一竣贪、第九天 我趴在偏房一處隱蔽的房頂上張望避乏。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至手报,卻和暖如春掩蛤,著一層夾襖步出監(jiān)牢的瞬間揍鸟,已是汗流浹背匾南。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留灯帮,地道東北人。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓迎献,卻偏偏與公主長得像,于是被迫代替她去往敵國和親冀瓦。 傳聞我的和親對象是個殘疾皇子写烤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評論 2 355

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