自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

TiFlink:使用TiKV和Flink實現(xiàn)強(qiáng)一致的物化視圖

開發(fā) 前端
本文介紹了使用Flink在TiKV上實現(xiàn)強(qiáng)一致的物化視圖的基本原理。以上原理已經(jīng)基本上在TiFlink系統(tǒng)中實現(xiàn),歡迎各位讀者試用。

 [[429973]]

在本年初的TiDB Hackathon上,我和一眾隊友嘗試使用Flink為TiDB添加物化視圖功能,并摘得了“最佳人氣獎”??梢哉f,物化視圖在這屆比賽中可謂是一個熱點。單單是結(jié)合Flink實現(xiàn)相關(guān)功能的隊伍就有三四個。必須承認(rèn)的是,在比賽結(jié)束時我們項目的完成度很低,雖然基本思路已經(jīng)定型,最終呈現(xiàn)的結(jié)果卻遠(yuǎn)沒達(dá)到預(yù)期。經(jīng)過半年多斷斷續(xù)續(xù)的修補(bǔ),在今天終于可以發(fā)布一個 預(yù)覽版本 給大家試用。這篇文章就是對我們思路和成果的一個介紹。

相比其他隊伍,我們的主要目標(biāo)是實現(xiàn)強(qiáng)一致的物化視圖構(gòu)建。也就是保證查詢時的物化視圖可以達(dá)到接近快照隔離(Snapshot Isolation)的隔離級別,而不是一般流處理系統(tǒng)的最終一致性(Eventual Consistency)。關(guān)于實現(xiàn)一致性的討論在下文有詳細(xì)介紹。

使用簡介

盡管是一個實驗性的項目,我們?nèi)匀惶剿髁艘恍┓奖銓嵱玫奶匦?,包括?/p>

  1. TiFlinkApp 

關(guān)于TiFlink實用的詳細(xì)信息,請參考 README 。下面是快速啟動一個任務(wù)的代碼片段:

  1. TiFlinkApp.newBuilder() 
  2.    .setJdbcUrl("jdbc:mysql://root@localhost:4000/test") // Please make sure the user has correct permission 
  3.    .setQuery( 
  4.        "select id, " 
  5.            + "first_name, " 
  6.            + "last_name, " 
  7.            + "email, " 
  8.            + "(select count(*) from posts where author_id = authors.id) as posts " 
  9.            + "from authors"
  10.    // .setColumnNames("a", "b", "c", "d") // Override column names inferred from the query 
  11.    // .setPrimaryKeys("a") // Specify the primary key columns, defaults to the first column 
  12.    // .setDefaultDatabase("test") // Default TiDB database to use, defaults to that specified by JDBC URL 
  13.    .setTargetTable("author_posts"// TiFlink will automatically create the table if not exist 
  14.    // .setTargetTable("test", "author_posts") // It is possible to sepecify the full table path 
  15.    .setParallelism(3// Parallelism of the Flink Job 
  16.    .setCheckpointInterval(1000// Checkpoint interval in milliseconds. This interval determines data refresh rate 
  17.    .setDropOldTable(true// If TiFlink should drop old target table on start 
  18.    .setForceNewTable(true// If to throw an error if the target table already exists 
  19.    .build() 
  20.    .start(); // Start the app 

物化視圖(流處理系統(tǒng))的一致性

目前主流的物化視圖(流處理)系統(tǒng)主要使用最終一致性。也就是說盡管最終結(jié)果會收斂到一致的狀態(tài),但在處理期間終端用戶仍可能查詢到一些不一致的結(jié)果。最終一致性在很多應(yīng)用中被證明是足夠的,那么更強(qiáng)的一致性是否真的需要呢?這里的一致性和Flink的Exact Once語義又有什么關(guān)系呢?有必要進(jìn)行一些介紹。

ACID

ACID是數(shù)據(jù)庫的一個基本的概念。一般來說,作為CDC日志來源的數(shù)據(jù)庫已經(jīng)保證了這四條要求。但是在使用CDC數(shù)據(jù)進(jìn)行流式處理的時候,其中的某些約束卻有可能被破壞。

最典型的情況是失去Atomic特性。這是因為在CDC 日志中,一個事務(wù)的修改可能覆蓋多條記錄,流處理系統(tǒng)如果以行為單位進(jìn)行處理,就有可能破壞原子性。也就是說,在結(jié)果集上進(jìn)行查詢的用戶看到的事務(wù)是不完整的。

一個典型的案例如下:

 

 

Change Log 與事務(wù)的原子性 

 

 

在上述案例中,我們有一個賬戶表,賬戶表之間會有轉(zhuǎn)賬操作,由于轉(zhuǎn)賬操作涉及多行修改,因此往往會產(chǎn)生多條記錄。假設(shè)我們有如下一條SQL定義的物化視圖,計算所有賬戶余額的總和:

  1. SELECT SUM(balance) FROM ACCOUNTS; 

顯然,如果我們只存在表內(nèi)賬戶之間的轉(zhuǎn)賬,這個查詢返回的結(jié)果應(yīng)該恒為某一常數(shù)。但是由于目前一般的流處理系統(tǒng)不能處理事務(wù)的原子性,這條查詢產(chǎn)生的結(jié)果卻可能是不斷波動的。實際上,在一個不斷并發(fā)修改的源表上,其波動甚至可能是無界的。

盡管在最終一致的模型下,上述查詢的結(jié)果在經(jīng)過一段時間之后將會收斂到正確值,但沒有原子性保證的物化視圖仍然限制的應(yīng)用場景:假設(shè)我想實現(xiàn)一個當(dāng)上述查詢結(jié)果偏差過大時進(jìn)行報警的工具,我就有可能會接收到很多虛假報警。也就是說此時在數(shù)據(jù)庫端并沒有任何異常,數(shù)值的偏差只是來源于流處理系統(tǒng)內(nèi)部。

在分布式系統(tǒng)中,還有另一種破壞原子性的情況,就是當(dāng)一個事務(wù)修改產(chǎn)生的副作用分布在多個不同的節(jié)點處。如果在這時不使用2PC等方法進(jìn)行分布式提交,則也會破壞原子性:部分節(jié)點(分區(qū))上的修改先于其他節(jié)點生效,從而出現(xiàn)不一致。

線性一致性

不同于由單機(jī)數(shù)據(jù)庫產(chǎn)生的CDC日志(如MySQL的Binlog),TiDB這類分布式數(shù)據(jù)庫產(chǎn)生的日志會有線性一致性的問題。在我們的場景下,線性一致性的問題可以描述為:從用戶的角度先后執(zhí)行的一些操作,其產(chǎn)生的副作用(日志)由于消息系統(tǒng)傳遞的延遲,以不同的先后順序被流處理系統(tǒng)處理。

假設(shè)我們有訂單表(ORDERS)和付款信息表(PAYMENTS)兩個表,用戶必須先創(chuàng)建訂單才能進(jìn)行支付,因此下列查詢的結(jié)果必然是正數(shù):

  1. WITH order_amount AS (SELECT SUM(amount) AS total FROM ORDERS), 
  2. WITH payment_amount AS (SELECT SUM(amount) AS total FROM PAYMENTS) 
  3. SELECT order_amount.total - payment_amount.total 
  4. FROM order_amount, payment_amount; 

但是由于ORDERS表和PAYMENTS表在分別存儲在不同的節(jié)點上,因此流處理系統(tǒng)消費(fèi)他們的速度可能是不一致的。也就是說,流處理系統(tǒng)可能已經(jīng)看到了支付信息的記錄,但是其對應(yīng)的訂單信息還沒到達(dá)。因此就可能觀察到上述查詢出現(xiàn)負(fù)數(shù)的結(jié)果。

在流處理系統(tǒng)中,有一個Watermark的概念可以用來同步不同表的數(shù)據(jù)的處理進(jìn)度,但是它并不能避免上述線性一致性問題。這是因為Watermark只要求時間戳小于其的所有記錄都已經(jīng)到達(dá),不要求時間戳大于其的記錄都沒有到達(dá)。也就是說,盡管ORDERS表和PAYMENTS表現(xiàn)在擁有相同的Watermark,后者仍然可能會有一些先到的記錄已經(jīng)生效。

由此可見,單純依靠Watermark本身是無法處理線性一致性問題的,必須和源數(shù)據(jù)庫的時間產(chǎn)生系統(tǒng)和消息系統(tǒng)配合。

更強(qiáng)一致性的需求

盡管最終一致性在很多場景下是夠用的,但其依然存在很多問題:

  1. 誤導(dǎo)用戶:由于很多用戶并不了解一致性相關(guān)的知識,或者對其存在一定的誤解,導(dǎo)致其根據(jù)尚未收斂的查詢結(jié)果做出了決策。這種情況在大部分關(guān)系型數(shù)據(jù)庫都默認(rèn)較強(qiáng)一致性的情況下是應(yīng)該避免的
  2. 可觀測性差:由于最終一致性并沒有收斂時間的保證,再考慮到線性一致性問題的存在,很難對流處理系統(tǒng)的延遲、數(shù)據(jù)新鮮度、吞吐量等指標(biāo)進(jìn)行定義。比如說用戶看到的JOIN的結(jié)果可能是表A當(dāng)前的快照和表B十分鐘前的快照聯(lián)接的結(jié)果,此時應(yīng)如何定義查詢結(jié)果的延遲度呢?
  3. 限制了部分需求的實現(xiàn):正如上文所提到的,由于不一致的內(nèi)部狀態(tài),導(dǎo)致某些告警需求要么無法實現(xiàn),要么需要延遲等待一段時間。否則用戶就不得不接受較高的誤報率

實際上,更強(qiáng)一致性的缺乏還導(dǎo)致了一些運(yùn)維操作,特別是DDL類的操作難以利用之前計算好的結(jié)果。參考關(guān)系型數(shù)據(jù)庫和NoSQL數(shù)據(jù)庫的發(fā)展歷史,我們相信目前主流的最終一致性只是受限于技術(shù)發(fā)展的權(quán)宜之計,隨著相關(guān)理論和技術(shù)研究的進(jìn)步,更強(qiáng)的一致性將會慢慢成為流處理系統(tǒng)的主流。

技術(shù)方案簡介

這里詳細(xì)介紹一下TiFlink在技術(shù)方案上的考慮,以及如何實現(xiàn)了強(qiáng)一致的物化視圖(StreamSQL)維護(hù)。

TiKV和Flink

盡管這是一個TiDB Hackthon項目,因此必然會選擇TiDB/TiKV相關(guān)的組件,但是在我看來TiKV作為物化視圖系統(tǒng)的中間存儲方案具備很多突出的優(yōu)勢:

  1. TiKV是一個比較成熟分布式KV存儲,而分布式環(huán)境是下一代物化視圖系統(tǒng)必須要支持的場景。利用TiKV配套的Java Client,我們可以方便的對其進(jìn)行操作。同時TiDB本身作為一個HTAP系統(tǒng),正好為物化視圖這個需求提供了一個Playground
  2. TiKV提供了基于Percolator模型的事務(wù)支持和MVCC,這是TiFlink實現(xiàn)強(qiáng)一致流處理的基礎(chǔ)。在下文中可以看到,TiFlink對TiKV的寫入主要是以接連不斷的事務(wù)的形式進(jìn)行的
  3. TiKV原生提供了對CDC日志輸出的支持。實際上TiCDC組件正是利用這一特性實現(xiàn)的CDC日志導(dǎo)出功能。在TiFlink中,為了實現(xiàn)批流一體并簡化系統(tǒng)流程,我們選擇直接調(diào)用TiKV的CDC GRPC接口,因此也放棄了TiCDC提供的一些特性

我們最初的想法本來是直接將計算功能集成進(jìn)TiKV,選擇Flink則是在比賽過程中進(jìn)一步思考后得到的結(jié)論。選擇Flink的主要優(yōu)勢有:

  1. Flink是目前市面上最成熟的Stateful流處理系統(tǒng),其對處理任務(wù)的表達(dá)能力強(qiáng),支持的語義豐富,特別是支持批流一體的StreamSQL實現(xiàn),是我們可以專心于探索我們比較關(guān)注的功能,如強(qiáng)一致性等
  2. Flink比較完整地Watermark,而我們發(fā)現(xiàn)其基于Checkpoint實現(xiàn)的Exactly Once Delivery語義可以很方便地和TiKV結(jié)合來實現(xiàn)事務(wù)處理。實際上,F(xiàn)link自己提供的一些支持Two Phase Commit的Sink就是結(jié)合Checkpoint來進(jìn)行提交的
  3. Flink的流處理(特別是StreamSQL)本身就基于物化視圖的理論,在比較新的版本開始提供的DynamicTable接口,就是為了方便將外部的Change Log引入系統(tǒng)。它已經(jīng)提供了對INSERT、DELETE、UPDATE等多種CDC操作的支持

當(dāng)然,選擇TiKV+Flink這樣的異構(gòu)架構(gòu)也會引入一些問題,比如SQL語法的不匹配,UDF無法共享等問題。在TiFlink中,我們以Flink的SQL系統(tǒng)和UDF為準(zhǔn),將其作為TiKV的一個外掛系統(tǒng)使用,但同時提供了方便的建表功能。

強(qiáng)一致的物化視圖的實現(xiàn)思路

這一部分將介紹TiFlink如何在TiDB/TiKV的基礎(chǔ)上實現(xiàn)一個比較強(qiáng)的一致性級別:延遲快照隔離(Stale Snapshot Isolation)。在這種隔離級別下,查詢者總是查詢到歷史上一個一致的快照狀態(tài)。在傳統(tǒng)的快照隔離中,要求查詢者在$T$時間能且只能觀察到Commit時間小于$T$的所有事務(wù)。而延遲快照隔離只能保證觀察到$T-\Delta t$之前所有已提交的事務(wù)。

在TiDB這樣支持事務(wù)的分布式數(shù)據(jù)庫上實現(xiàn)強(qiáng)一致的物化視圖,最簡單的思路就是使用一個接一個的事務(wù)來更新視圖。事務(wù)在開始時讀取到的是一個一致的快照,而使用分布式事務(wù)對物化視圖進(jìn)行更新,本身也是一個強(qiáng)一致的操作,且具有ACID的特性,因此得以保證一致性。

為了將Flink和這樣的機(jī)制結(jié)合起來且實現(xiàn)增量維護(hù),我們利用了TiKV本身已經(jīng)提供的一些特性:

  1. TiKV使用Time Oracle為所有的操作分配時間戳,因此雖然是一個分布式系統(tǒng),其產(chǎn)生的CDC日志中的事務(wù)的時間戳實際上是有序的
  2. TiKV的節(jié)點(Region)可以產(chǎn)生連續(xù)不斷的增量日志(Change Log),這些日志包含了事務(wù)的各種原始信息并包含時間戳信息
  3. TiKV的增量日志會定期產(chǎn)生Resolved Timestamp,聲明當(dāng)前Region不再會產(chǎn)生時間戳更老的消息。因此很適合用來做Watermark
  4. TiKV提供了分布式事務(wù),允許我們控制一批修改的可見性

因此TiFlink的基本實現(xiàn)思路就是:

  1. 利用流批一體的特性,以某全局時間戳對源表進(jìn)行快照讀取,此時可以獲得所有源表的一個一致性視圖
  2. 切換到增量日志消費(fèi),利用Flink的DynamicTable相關(guān)接口,實現(xiàn)物化視圖的增量維護(hù)和輸出
  3. 以一定的節(jié)奏Commit修改,使得所有的修改以原子的事務(wù)方式寫入目標(biāo)表,從而為物化視圖提供一個又一個更新視圖

以上幾點的關(guān)鍵在于協(xié)調(diào)各個節(jié)點一起完成分布式事務(wù),因此有必要介紹一下TiKV的分布式事務(wù)執(zhí)行原理。

TiKV的分布式事務(wù)

TiKV的分布式事務(wù)基于著名的Percolator模型。Percolator模型本身要求存儲層的KV Store有MVCC的支持和單行讀寫的原子性和樂觀鎖(OCC)。在此基礎(chǔ)上它采用以下步驟完成一次事務(wù):

  1. 指定一個事務(wù)主鍵(Primary Key)和一個開始時間戳并寫入主鍵
  2. 其他行在Prewrite時以副鍵(Secondary Key)的形式寫入,副鍵會指向主鍵并具有上述開始時間戳
  3. 在所有節(jié)點Prewrite完成后,可以提交事務(wù),此時應(yīng)先Commit主鍵,并給定一個Commit時間戳
  4. 主鍵Commit成功后事務(wù)實際上已經(jīng)提交成功,但此時為了方便讀取,可以多節(jié)點并發(fā)地對副鍵進(jìn)行Commit并執(zhí)行清理工作,之后寫入的行都將變?yōu)榭梢?/li>

上述分布式事務(wù)之所以可行,是因為對主鍵的Commit是原子的,分布在不同節(jié)點的副鍵是否提交成功完全依賴于主鍵,因此其他的讀取者在讀到Prewrite后但還沒Commit的行時,會去檢查主鍵是否已Commit。讀取者也會根據(jù)Commit時間戳判斷某一行數(shù)據(jù)是否可見。Cleanup操作如果中途故障,在之后的讀取者也可以代行。

為了實現(xiàn)快照隔離,Percolator要求寫入者在寫入時檢查并發(fā)的Prewrite記錄,保證他們的時間戳符合一定的要求才能提交事務(wù)。本質(zhì)上是要求寫入集重疊的事務(wù)不能同時提交。在我們的場景中假設(shè)物化視圖只有一個寫入者且事務(wù)是連續(xù)的,因此無需擔(dān)心這點。

在了解了TiKV的分布式事務(wù)原理之后,要考慮的就是如何將其與Flink結(jié)合起來。在TiFlink里,我們利用Checkpoint的機(jī)制來實現(xiàn)全局一致的事務(wù)提交。

使用Flink進(jìn)行分布式事務(wù)提交

從上面的介紹可以看出,TiKV的分布式事務(wù)提交可以抽象為一次2PC。Flink本身有提供實現(xiàn)2PC的Sink,然而并不能直接用在我們的場景下。原因是Percolator模型在提交時需要有全局一致的事務(wù)開始時間戳和提交時間戳。而且僅僅是在Sink端實現(xiàn)2PC是不足以實現(xiàn)強(qiáng)一致隔離級別的:我們還需要在Source端配合,使得每個事務(wù)恰好讀入所需的增量日志。

幸運(yùn)的是,F(xiàn)link的2PC提交機(jī)制實際上是由Checkpoint驅(qū)動的:當(dāng)Sink接收到Checkpoint請求時,會完成必要的任務(wù)以進(jìn)行提交。受此啟發(fā),我們可以實現(xiàn)一對Source和Sink,讓他們使用Checkpoint的ID共享Transaction的信息,并配合Checkpoint的過程完成2PC。而為了使不同節(jié)點可以對事務(wù)的信息(時間戳,主鍵)等達(dá)成一致,需要引入一個全局協(xié)調(diào)器。事務(wù)和全局協(xié)調(diào)器的接口定義如下:

  1. public interface Transaction { 
  2.  
  3.   public enum Status { 
  4.     NEW, 
  5.     PREWRITE, 
  6.     COMMITTED, 
  7.     ABORTED; 
  8.   }; 
  9.  
  10.   long getCheckpointId(); 
  11.  
  12.   long getStartTs(); 
  13.  
  14.   default long getCommitTs(); 
  15.  
  16.   default byte[] getPrimaryKey(); 
  17.  
  18.   default Status getStatus(); 
  19.  
  20. public interface Coordinator extends AutoCloseable, Serializable { 
  21.   Transaction openTransaction(long checkpointId); 
  22.  
  23.   Transaction prewriteTransaction(long checkpointId, long tableId); 
  24.  
  25.   Transaction commitTransaction(long checkpointId); 
  26.  
  27.   Transaction abortTransaction(long checkpointId); 

使用上述接口,各個Source和Sink節(jié)點可以使用CheckpointID開啟事務(wù)或獲得事務(wù)ID,協(xié)調(diào)器會負(fù)責(zé)分配主鍵并維護(hù)事務(wù)的狀態(tài)。為了方便起見,事務(wù)Commit時對主鍵的提交操作也放在協(xié)調(diào)器中執(zhí)行。協(xié)調(diào)器的實現(xiàn)有很多方法,目前TiFlink使用最簡單的實現(xiàn):在JobManager所在進(jìn)程中啟動一個GRPC服務(wù)?;赥iKV的PD(ETCD)或TiKV本身實現(xiàn)分布式的協(xié)調(diào)器也是可能的。

 

 

事務(wù)與Checkpoint的協(xié)調(diào)執(zhí)行 

 

上圖展示了在Flink中執(zhí)行分布式事務(wù)和Checkpoint之間的協(xié)調(diào)關(guān)系。一次事務(wù)的具體過程如下:

  1. Source先從TiKV接收到增量日志,將他們按照時間戳Cache起來,等待事務(wù)的開始
  2. 當(dāng)Checkpoint進(jìn)程開始時,Source會先接收到信號。在Source端的Checkpoint與日志接收服務(wù)運(yùn)行在不同的線程中
  3. Checkpoint線程先通過全局協(xié)調(diào)器獲得當(dāng)前事務(wù)的信息(或開啟一個新事務(wù)),分布式情況下一個CheckpointID對應(yīng)的事務(wù)只會開啟一次
  4. 得到事務(wù)的開始時間戳后,Source節(jié)點開始將Cache中小于此時間戳的已提交修改Emit到下游計算節(jié)點進(jìn)行消費(fèi)。此時Source節(jié)點也會Emit一些Watermark
  5. 當(dāng)所有Source節(jié)點完成上述操作后,Checkpoint在Source節(jié)點成功完成,此后會向后繼續(xù)傳播,根據(jù)Flink的機(jī)制,Checkpoint在每個節(jié)點都會保證其到達(dá)之前的所有Event都已被消費(fèi)
  6. 當(dāng)Checkpoint到達(dá)Sink時,之前傳播到Sink的Event都已經(jīng)被Prewrite過了,此時可以開始事務(wù)的提交過程。Sink在內(nèi)部狀態(tài)中持久化事務(wù)的信息,以便于錯誤時恢復(fù),在所有Sink節(jié)點完成此操作后,會在回調(diào)中調(diào)用協(xié)調(diào)器的Commit方法從而提交事務(wù)
  7. 提交事務(wù)后,Sink會啟動線程進(jìn)行Secondary Key的清理工作,同時開啟一個新的事務(wù)

注意到,在第一個Checkpoint開始前,Sink可能已經(jīng)開始接收到寫入的數(shù)據(jù)了,而此時它還沒有事務(wù)的信息。為了解決這一問題,TiFlink在任務(wù)開始時會直接啟動一個初始事務(wù),其對應(yīng)的CheckpointID是0,用于提交最初的一些寫入。這樣的話,在 CheckpointID=1 的Checkpoint完成時,實際上提交的是這個0事務(wù)。事務(wù)和Checkpoint以這樣的一種錯位的方式協(xié)調(diào)執(zhí)行。

下圖展示了包含協(xié)調(diào)器在內(nèi)的整個TiFlink任務(wù)的架構(gòu):

 

 

 

TiFlink的系統(tǒng)架構(gòu) 

 

基于以上的系統(tǒng)設(shè)計,我們就得到了一個在TiKV上實現(xiàn)延遲快照隔離的物化視圖。

其他設(shè)計考慮

眾所周知,KSQL是Flink之外另一個流行的流處理系統(tǒng),它直接與Kafka消息隊列系統(tǒng)結(jié)合,用戶無需部署兩套處理系統(tǒng),因此受到一些用戶的青睞。很多用戶也使用KSQL實現(xiàn)類似物化視圖這樣的需求。然而在我看來,這種強(qiáng)耦合于消息隊列的流處理系統(tǒng)并不適合物化視圖的使用場景。

KSQL可以說是Log Oriented數(shù)據(jù)處理系統(tǒng)的的代表,在這種系統(tǒng)中,數(shù)據(jù)的本源在于日志信息,所有的表都是為了方便查詢而消費(fèi)日志信息從而構(gòu)建出來的視圖。這種系統(tǒng)具有模型簡單、容易實現(xiàn)、可以長時間保存日志記錄等優(yōu)點。

與之相對是Table Oriented數(shù)據(jù)處理系統(tǒng),MySQL、TiDB/TiKV都屬于這一類系統(tǒng)。這一類系統(tǒng)的所有修改操作都作用于表數(shù)據(jù)結(jié)構(gòu),雖然期間也會有日志生成,但往往對表數(shù)據(jù)結(jié)構(gòu)和日志的修改是一起協(xié)調(diào)進(jìn)行的。這里日志的主要是為持久化和事務(wù)服務(wù),往往不會留存太長時間。相比于Log Oriented數(shù)據(jù)處理系統(tǒng),這類系統(tǒng)對寫入和事務(wù)的處理都更為復(fù)雜一點,然而卻擁有更強(qiáng)可擴(kuò)展性的要求。

歸根結(jié)底,這是因為Log Oriented系統(tǒng)中的數(shù)據(jù)是以日志的形式存儲,因此在擴(kuò)展時往往需要進(jìn)行成本較高的Rehash,也更難實現(xiàn)再平衡。而Table Oriented的系統(tǒng),數(shù)據(jù)主要以表的形式存儲,因此可以以某些列進(jìn)行有序排列,從而方便在一致性Hash的支持下實現(xiàn)Range的切分、合并和再平衡。

個人認(rèn)為,在批流一體的物化視圖場景下,長時間保存日志并無太大的意義(因為總是可以從源表的快照恢復(fù)數(shù)據(jù))。相反,隨著業(yè)務(wù)的發(fā)展不斷擴(kuò)展數(shù)據(jù)處理任務(wù)和視圖是一件比較重要的事。從這個角度來看Table Oriented系統(tǒng)似乎更適合作為物化視圖需求的存儲承載介質(zhì)。

當(dāng)然,在實時消費(fèi)增量Log時發(fā)生的分區(qū)合并或分裂是一個比較難處理的問題。TiKV在這種情況下會拋出一個GRPC錯誤。TiFlink目前使用的是比較簡單的靜態(tài)映射方法處理任務(wù)和分區(qū)之間的關(guān)系,在未來可以考慮更為合理的解決方案。

總結(jié)

本文介紹了使用Flink在TiKV上實現(xiàn)強(qiáng)一致的物化視圖的基本原理。以上原理已經(jīng)基本上在TiFlink系統(tǒng)中實現(xiàn),歡迎各位讀者試用。以上所有的討論都基于Flink的最終一致模型的保證,即:流計算的結(jié)果只與消費(fèi)的Event和他們在自己流中的順序有關(guān),與他們到達(dá)系統(tǒng)的順序以及不同流之間的相對順序無關(guān)。

目前的TiFlink系統(tǒng)還有很多值得提高的點,如:

  1. 支持非Integer型主鍵和聯(lián)合主鍵
  2. 更好的TiKV Region到Flink任務(wù)的映射
  3. 更好的Fault Tolerance和任務(wù)中斷時TiKV事務(wù)的清理工作
  4. 完善的單元測試

如果各位讀者對TiFlink感興趣的話,歡迎試用并提出反饋意見,如果能夠貢獻(xiàn)代碼幫助完善這個系統(tǒng)那就再好不過了。

關(guān)于物化視圖系統(tǒng)一致性的思考是我今年最主要的收獲之一。實際上,最初我們并沒有重視這一方面,而是在不斷地交流當(dāng)中才認(rèn)識到這是一個有價值且很有挑戰(zhàn)性的問題。通過TiFlink的實現(xiàn),可以說是基本上驗證了上述方法實現(xiàn)延遲快照一致性的可行性。當(dāng)然,由于個人的能力水平有限,如果存在什么紕漏,也歡迎各位提出討論。

最后,如果我們假設(shè)上述延遲快照一致性的論述是正確的,那么實現(xiàn)真正的快照隔離的方法也就呼之欲出。不知道各位讀者能否想到呢?

責(zé)任編輯:張燕妮 來源: 知乎
相關(guān)推薦

2021-12-26 00:48:05

一致性視圖數(shù)據(jù)庫

2010-08-02 13:25:23

DB2物化視圖

2024-11-19 08:09:09

MySQL數(shù)據(jù)庫數(shù)據(jù)

2017-03-24 16:54:52

PhxSQL微信開源MySQL

2009-05-06 11:09:10

Oracle物化視圖數(shù)據(jù)庫

2023-10-23 08:01:10

Redis同步全量復(fù)制

2010-07-27 14:26:08

DB2數(shù)據(jù)庫物化視圖

2009-11-17 15:59:25

Oracle物化視圖

2017-04-24 08:46:45

哈希函數(shù)算法負(fù)載

2020-11-24 09:03:41

一致性MySQLMVCC

2024-10-18 10:04:01

2021-05-19 21:50:46

Hash算法測試

2010-07-30 17:46:46

DB2物化視圖

2016-12-21 14:06:55

日志實現(xiàn)數(shù)據(jù)實時抽取

2016-12-19 18:41:09

哈希算法Java數(shù)據(jù)

2023-06-25 09:44:00

一致性哈希數(shù)據(jù)庫

2009-11-17 16:47:09

Oracle物化視圖日

2022-11-10 07:49:09

hash算法代碼

2013-04-03 10:01:42

JavaequalsObject

2017-07-25 14:38:56

數(shù)據(jù)庫一致性非鎖定讀一致性鎖定讀
點贊
收藏

51CTO技術(shù)棧公眾號