唐永金,孫家博,蔡 鵬
(華東師范大學(xué) 數(shù)據(jù)科學(xué)與工程學(xué)院,上海 200062)
隨著互聯(lián)網(wǎng)技術(shù)的快速發(fā)展,無論是互聯(lián)網(wǎng)企業(yè)還是傳統(tǒng)金融機(jī)構(gòu),業(yè)務(wù)積累的數(shù)據(jù)量都在快速增長(zhǎng).為了充分挖掘數(shù)據(jù)潛能,人們需要對(duì)數(shù)據(jù)進(jìn)行實(shí)時(shí)分析處理.但是數(shù)據(jù)分析要消耗大量系統(tǒng)資源,在處理OLTP (Online Transaction Processing) 和OLAP (Online Analytical Processing) 請(qǐng)求時(shí)需要做好資源隔離,否則,OLAP 處理會(huì)嚴(yán)重影響OLTP 的性能以及應(yīng)用端的用戶體驗(yàn).因此,現(xiàn)有的混合事務(wù)分析處理 (Hybrid Transactional Analytical Processing,HTAP) 系統(tǒng)大多采用解耦存儲(chǔ)設(shè)計(jì)[1],即將OLTP 和OLAP 的數(shù)據(jù)分布在不同的副本.在解耦存儲(chǔ)的 HTAP 系統(tǒng)中,OLTP 負(fù)責(zé)處理讀寫事務(wù)請(qǐng)求,將產(chǎn)生的日志發(fā)送給OLAP,OLAP 將收到的日志進(jìn)行回放并更新到本地,為數(shù)據(jù)分析提供數(shù)據(jù).
解耦存儲(chǔ)后雖然做到了資源隔離,但是也產(chǎn)生了數(shù)據(jù)新鮮度問題[2],即OLAP 端的數(shù)據(jù)相較OLTP 存在延遲.對(duì)于一些實(shí)時(shí)分析場(chǎng)景,例如,系統(tǒng)監(jiān)控、在線購物、無人駕駛等,數(shù)據(jù)新鮮度對(duì)分析結(jié)果有著非常重要的影響.在這些實(shí)時(shí)分析場(chǎng)景下,分析預(yù)測(cè)結(jié)果的準(zhǔn)確性主要依賴于OLTP 端中所產(chǎn)生的最新數(shù)據(jù)[3-5].OLAP 端數(shù)據(jù)新鮮度的主要影響因素包含日志發(fā)送速度和日志回放速度.HTAP 系統(tǒng)在實(shí)際應(yīng)用中,事務(wù)處理和查詢分析負(fù)載通常來自不同的應(yīng)用,實(shí)時(shí)分析應(yīng)用往往只需要訪問OLTP 端所產(chǎn)生的最新事務(wù)數(shù)據(jù)的小部分.基于表分組的日志并行回放方法[6]設(shè)計(jì)了針對(duì)表日志量的回放資源分配優(yōu)化.但是這種算法從本質(zhì)上,對(duì)每個(gè)表的日志都是一視同仁的,沒有根據(jù)HTAP 工作負(fù)載的特點(diǎn)專門設(shè)計(jì).
本文工作的目標(biāo)是為HTAP 系統(tǒng)提供一種更高效的并且側(cè)重提高OLAP 數(shù)據(jù)新鮮度的數(shù)據(jù)同步方法.本文在基于表分組的日志并行回放方法基礎(chǔ)上,引入針對(duì)HTAP 工作負(fù)載特點(diǎn)的專門優(yōu)化.根據(jù) OLAP 端查詢頻率將表分為高頻查詢表和低頻查詢表.在保障數(shù)據(jù)一致性的前提下,OLTP 端實(shí)現(xiàn)了高頻查詢表優(yōu)先的日志發(fā)送方法.同時(shí),本文所使用的日志并行回放方法也針對(duì)高頻查詢表做了優(yōu)化.引入優(yōu)先級(jí)的日志發(fā)送方法,會(huì)導(dǎo)致不同表的日志回放隊(duì)列可能存在較大的負(fù)載壓力差距,進(jìn)而產(chǎn)生數(shù)據(jù)傾斜問題.為保證回放效率,設(shè)計(jì)了基于負(fù)載壓力的動(dòng)態(tài)資源分配方法.解決了高頻查詢表日志優(yōu)先發(fā)送導(dǎo)致的亂序日志沖突.通過版本號(hào)解決行的寫寫沖突,同時(shí)設(shè)計(jì)事務(wù)提交日志隊(duì)列組,實(shí)現(xiàn)主節(jié)點(diǎn)和副本節(jié)點(diǎn)相同表的事務(wù)提交順序一致.
綜上所述,本文的主要結(jié)果為:
(1) 提出了由OLAP 端表查詢頻率驅(qū)動(dòng)的優(yōu)先級(jí)數(shù)據(jù)同步方法;
(2) 基于動(dòng)態(tài)分配思想解決了高頻查詢表的數(shù)據(jù)傾斜問題;
(3) 設(shè)計(jì)了針對(duì)優(yōu)先級(jí)數(shù)據(jù)同步的亂序日志沖突解決方案;
(4) 通過原型系統(tǒng)TPLR (Table-ID Based Parallel Log Replay)驗(yàn)證了本文方案的有效性.
為了有效保證OLTP 端和OLAP 端數(shù)據(jù)的隔離性,在解耦存儲(chǔ)的HTAP 系統(tǒng)中,分別為OLTP端和OLAP 端構(gòu)建一個(gè)獨(dú)立的數(shù)據(jù)庫實(shí)例.
通過ETL (Extract Transform Load) 更新數(shù)據(jù)倉庫的傳統(tǒng)方法能夠提供較好的性能隔離,但是由于其更新周期較長(zhǎng),OLAP 端在分析查詢時(shí)無法保證數(shù)據(jù)的新鮮度.BatchDB[7]為了保證 OLTP 端和OLAP 端的隔離性,使用副本在不同的機(jī)器上或者在同一個(gè)機(jī)器不同的NUMA (Non-Uniform Memory Access) 節(jié)點(diǎn)上,并采用周期性同步和 OLAP 端主動(dòng)請(qǐng)求同步兩種同步方式來保證數(shù)據(jù)新鮮度.Oracle 提出雙重格式[8],在內(nèi)存中針對(duì)OLTP 端以行格式存儲(chǔ)數(shù)據(jù)、OLAP 端以列格式存儲(chǔ)數(shù)據(jù),在執(zhí)行查詢時(shí),會(huì)結(jié)合OLTP 端的日志返回最新的數(shù)據(jù)來保證數(shù)據(jù)的新鮮度.Micorsoft SQL Server[9]也是維護(hù)了兩份副本,其通過避免同步OLTP 端被頻繁修改熱數(shù)據(jù)的方式來減小數(shù)據(jù)同步開銷.F1 Lightning[10]將HTAP 作為一種服務(wù),用來連接相互獨(dú)立的 OLTP 端和 OLAP 端.這種解耦合的HTAP 設(shè)計(jì)能減少OLAP 對(duì)OLTP 端的影響.F1 Lightning 要求在每次執(zhí)行查詢操作時(shí),OLAP 端都默認(rèn)使用最大的安全查詢時(shí)間戳,這種設(shè)計(jì)給數(shù)據(jù)新鮮度帶來負(fù)面影響.TiDB[11]為 OLTP 端和OLAP 端使用獨(dú)立的數(shù)據(jù)存儲(chǔ),基于Raft 協(xié)議保證數(shù)據(jù)的一致性和高可用性.在執(zhí)行查詢操作時(shí),OLAP 端會(huì)發(fā)起校對(duì)和更新請(qǐng)求,在確保數(shù)據(jù)包含讀取請(qǐng)求時(shí)間戳之后才會(huì)返回?cái)?shù)據(jù).
傳統(tǒng)的串行日志回放方式,無法發(fā)揮機(jī)器多核優(yōu)勢(shì),導(dǎo)致在負(fù)載壓力較大的情況下,副本節(jié)點(diǎn)的數(shù)據(jù)版本遠(yuǎn)遠(yuǎn)落后于主節(jié)點(diǎn)數(shù)據(jù)版本.并行日志回放技術(shù)的核心問題是確定性 (數(shù)據(jù)一致性的保證)和并發(fā)性 (多核架構(gòu)上的性能需求) 之間的矛盾.MySQL (My Structure Quest Language) 在5.7 版本提出組提交技術(shù),MySQL 在主節(jié)點(diǎn)對(duì)事務(wù)分組,按組進(jìn)行提交,同一個(gè)組內(nèi)事務(wù)不沖突.在日志里添加組提交信息,副本節(jié)點(diǎn)回放時(shí)根據(jù)組提交信息,對(duì)同一小組的事務(wù)并行回放.這種方法的并行度依賴主節(jié)點(diǎn)的事務(wù)并行度,因此,在主節(jié)點(diǎn)事務(wù)沖突嚴(yán)重的情況下,日志回放的并行度會(huì)很低.KuaFu[12]保證并行回放的方式是在回放前通過分析日志生成一個(gè)寫寫依賴圖,讓無依賴關(guān)系的事務(wù)可以并行回放.但是,分析和建立事務(wù)依賴圖的性能開銷較大,并且依賴圖以事務(wù)粒度的解決沖突仍然對(duì)并行度有所限制.Taurus[13]針對(duì)內(nèi)存數(shù)據(jù)庫的單流日志方案提出了一種并行日志回放方案.該方案兼容數(shù)據(jù)日志和命令日志,使用多個(gè)日志流提高主節(jié)點(diǎn)日志回放速度.Taurus[13]引入一種叫做日志序列向量的輕量級(jí)依賴跟蹤機(jī)制,基于該向量捕獲事務(wù)之間的依賴關(guān)系,確保在日志記錄恢復(fù)中正確執(zhí)行依賴關(guān)系.日志序列向量在日志數(shù)據(jù)量較大的情況下,記錄和跟蹤事務(wù)依賴關(guān)系會(huì)產(chǎn)生較大的開銷.
針對(duì)多版本數(shù)據(jù)庫的日志并行回放也存在一定的技術(shù)挑戰(zhàn).由于數(shù)據(jù)是多版本的,并發(fā)回放使得用戶在讀取數(shù)據(jù)時(shí),所需的版本可能還不存在,即使存在也無法確定是否為正確的版本.為了解決這個(gè)問題,可以將主節(jié)點(diǎn)記錄的所有可能的版本也傳送給副本節(jié)點(diǎn),使得副本節(jié)點(diǎn)可以根據(jù)事務(wù)的順序推斷出所要讀取的正確版本,保證回放可以并發(fā)執(zhí)行.
在傳統(tǒng)的并行日志回放方法中,為了判斷事務(wù)間是否存在沖突,需要檢查并判斷事務(wù)間的依賴關(guān)系,這個(gè)過程將會(huì)對(duì)系統(tǒng)產(chǎn)生較大的性能影響.學(xué)術(shù)界也提出了一種基于Session ID 的日志調(diào)度回放方法[14],將日志按Session ID 分組,高效分發(fā)給日志并行回放器,比起傳統(tǒng)基于Transaction ID 的方法減少了并行回放線程之間不必要的沖突.這種方法在日志并行回放產(chǎn)生沖突時(shí),依然以事務(wù)為粒度進(jìn)行阻塞等待.
在現(xiàn)有工作中,有將日志根據(jù)表分組并行優(yōu)化的方法[6],每個(gè)表擁有自己獨(dú)立的回放隊(duì)列,并且回放隊(duì)列的線程資源是根據(jù)所對(duì)應(yīng)表的日志總量動(dòng)態(tài)調(diào)整的.這種方法對(duì)于不同表之間仍然是平等的,比較適合主備負(fù)載擁有相同數(shù)據(jù)特征的場(chǎng)景,沒有對(duì)于HTAP 這種主備負(fù)載差別明顯的場(chǎng)景進(jìn)行優(yōu)化.
本文設(shè)計(jì)了實(shí)現(xiàn)多版本的內(nèi)存數(shù)據(jù)庫原型TPLR,圖1 展示了TPLR 系統(tǒng)架構(gòu).TPLR 主要基于MySQL 中日志生成和回放模塊進(jìn)行修改實(shí)現(xiàn).TPLR 系統(tǒng)架構(gòu)由OLTP 主節(jié)點(diǎn)和OLAP 副本節(jié)點(diǎn)構(gòu)成,并通過網(wǎng)絡(luò)互連.TPLR 中主節(jié)點(diǎn)接收事務(wù)處理請(qǐng)求,副本節(jié)點(diǎn)負(fù)責(zé)查詢分析請(qǐng)求.主節(jié)點(diǎn)定時(shí)同步副本節(jié)點(diǎn)的查詢統(tǒng)計(jì)數(shù)據(jù),分析統(tǒng)計(jì)數(shù)據(jù),將表分為高頻查詢表和低頻查詢表.在日志發(fā)送階段,經(jīng)過日志發(fā)送模塊的預(yù)處理,在保證數(shù)據(jù)一致性前提下,提升高頻查詢表的發(fā)送優(yōu)先級(jí).日志傳送到副本節(jié)點(diǎn)后,由日志調(diào)度模塊負(fù)責(zé)解析日志,并根據(jù)解析得到的Table-ID 等信息對(duì)日志進(jìn)行分發(fā)調(diào)度.日志回放模塊負(fù)責(zé)對(duì)日志并行回放,同時(shí)根據(jù)任務(wù)隊(duì)列的負(fù)載壓力,動(dòng)態(tài)調(diào)整回放線程資源,事務(wù)所對(duì)應(yīng)的日志記錄完成回放并提交后,相應(yīng)的數(shù)據(jù)記錄才對(duì)查詢操作可見.副本節(jié)點(diǎn)面對(duì)客戶端的查詢請(qǐng)求,需要檢查當(dāng)前數(shù)據(jù)是否滿足數(shù)據(jù)新鮮度要求,如果目前數(shù)據(jù)狀態(tài)無法滿足,請(qǐng)求就需要等待日志回放與數(shù)據(jù)更新.
圖1 TPLR 系統(tǒng)架構(gòu)Fig.1 TPLR system architecture
TPLR 的數(shù)據(jù)記錄格式主要特點(diǎn)是通過一個(gè)版本鏈來連接不同的版本,每條所記錄的元數(shù)據(jù)除了包含主鍵和值外,還包含事務(wù)號(hào)、時(shí)間戳和行版本號(hào).事務(wù)號(hào)表示主節(jié)點(diǎn)中事務(wù)的提交順序,時(shí)間戳表示事務(wù)在主節(jié)點(diǎn)提交的物理時(shí)間,行版本號(hào)表示該條記錄被實(shí)際修改的次數(shù),在副本節(jié)點(diǎn)中可以用于解決寫寫沖突.TPLR 在日志生成階段和常規(guī)日志相比添加了行版本號(hào),事務(wù)DML (Data Manipulation Language) 操作數(shù)以及事務(wù)處理表數(shù),主要是為了幫助解決副本節(jié)點(diǎn)中的數(shù)據(jù)一致性問題.
本文數(shù)據(jù)同步所使用的日志格式為行級(jí)日志,該日志記錄數(shù)據(jù)庫表結(jié)構(gòu)變更以及每一行記錄被修改的形式.行級(jí)日志不會(huì)記錄類似select 和show 這些對(duì)數(shù)據(jù)本身無影響的操作,因此,只讀操作不會(huì)影響數(shù)據(jù)同步.常規(guī)行級(jí)日志相關(guān)字段包括日志類型、事務(wù)號(hào)、操作類型、主鍵和值等.本文為保證數(shù)據(jù)一致性額外添加了一些新字段.
在日志處理過程中,需要根據(jù)日志類型信息將數(shù)據(jù)操縱語言日志和事務(wù)提交日志分開處理.其中DML 日志包含主節(jié)點(diǎn)插入、刪除、更新操作,記錄表結(jié)構(gòu)和表數(shù)據(jù)的變化.事務(wù)提交日志記錄事務(wù)提交時(shí)的相關(guān)信息,一般作為事務(wù)完成的標(biāo)志.
本文實(shí)現(xiàn)原型使用了多版本并發(fā)控制技術(shù).這種技術(shù)使得對(duì)行記錄的修改不會(huì)覆蓋舊數(shù)據(jù),而是創(chuàng)建一個(gè)新版本記錄,因此,需要在DML 日志中添加行版本號(hào)信息來保證在并行回放時(shí),對(duì)數(shù)據(jù)行的更新順序.
在事務(wù)提交日志中,所添加的事務(wù)DML 操作數(shù) (Transaction DML Numbers,TDN) 主要記錄每個(gè)事務(wù)中DML 記錄數(shù).在日志并行回放過程中,事務(wù)提交日志與DML 日志并行被處理,事務(wù)提交日志需要先根據(jù)DML 操作數(shù)確定是否所有DML 日志都回放完畢,再確定是否進(jìn)行事務(wù)提交.
事務(wù)提交日志還增加事務(wù)處理表數(shù) (Number of Tables in the Transaction,NTT),記錄每個(gè)事務(wù)中涉及DML 操作的表的個(gè)數(shù).NTT 主要是區(qū)分事務(wù)是否涉及多個(gè)表.如果事務(wù)涉及多個(gè)表,則需要按照串行順序發(fā)送,否則將其視為單表事務(wù),根據(jù)查詢頻率分類,對(duì)發(fā)送順序進(jìn)行調(diào)整,例如,將高頻查詢表事務(wù)日志優(yōu)先傳送.
TPLR 基于查詢頻率的日志發(fā)送方法的基本思想是在能保證數(shù)據(jù)一致性的前提下,優(yōu)先發(fā)送高頻查詢表,即通過OLAP 端的查詢頻率來決定日志發(fā)送優(yōu)先級(jí).圖2 為日志發(fā)送預(yù)處理的流程.首先,將待發(fā)送日志數(shù)據(jù)解析后存到發(fā)送緩沖區(qū);然后,在緩沖區(qū)中將日志根據(jù)NTT 分為單表事務(wù)和多表事務(wù);最后,當(dāng)緩沖區(qū)填滿時(shí),對(duì)日志進(jìn)行預(yù)處理,目的是提升高頻查詢表的傳送優(yōu)先級(jí).不過這里對(duì)于多表事務(wù)不能進(jìn)行預(yù)處理,因?yàn)闊o法根據(jù)表查詢頻率判斷多表事務(wù)的提交順序.
圖2 日志發(fā)送預(yù)處理Fig.2 Log sending preprocessing
TPLR 日志并行回放的基本思想是多線程并行處理DML 日志,同時(shí)解決多線程處理的數(shù)據(jù)一致性問題.在回放過程中重點(diǎn)優(yōu)化回放速度,盡可能減少不必要的沖突,最小化系統(tǒng)的可見性延遲.圖3展示了日志調(diào)度和日志回放.
圖3 日志調(diào)度和日志回放Fig.3 Log scheduling and log replay
日志調(diào)度流程主要分為以下3 步.
(1) 副本節(jié)點(diǎn)的日志調(diào)度器收到主節(jié)點(diǎn)發(fā)送的日志數(shù)據(jù)后,將會(huì)對(duì)日志數(shù)據(jù)進(jìn)行初步解析和切分成獨(dú)立的日志記錄.
(2) 日志調(diào)度器根據(jù)日志記錄的類型和表名,對(duì)日志記錄進(jìn)行分組.日志記錄的類型是 DML 操作日志,將會(huì)根據(jù)表名被分配到該表所對(duì)應(yīng)的 DML 日志隊(duì)列.日志的類型是事務(wù)提交日志,則根據(jù)TNN 判斷日志相對(duì)應(yīng)的事務(wù)是否為單表事務(wù),對(duì)單表事務(wù)只需要將日志放入相對(duì)應(yīng)事務(wù)提交隊(duì)列,對(duì)多表事務(wù)則將日志復(fù)制多份,添加到每個(gè)表所對(duì)應(yīng)的日志提交隊(duì)列.
(3) 日志調(diào)度器完成對(duì)日志記錄的分配后,副本節(jié)點(diǎn)中每個(gè)表所對(duì)應(yīng)的回放線程將會(huì)同時(shí)回放所負(fù)責(zé)的日志記錄.圖3 中每個(gè)日志隊(duì)列后分配的回放線程數(shù)不同,體現(xiàn)了資源分配的動(dòng)態(tài)性.當(dāng)事務(wù)所對(duì)應(yīng)的日志記錄回放完成且該事務(wù)的提交日志記錄位于事務(wù)提交日志隊(duì)列的隊(duì)頭時(shí),該事務(wù)可提交.當(dāng)事務(wù)完成提交后,該事務(wù)所對(duì)應(yīng)的數(shù)據(jù)記錄對(duì)查詢操作可見.
在并行日志回放過程中,必須保證查詢操作在副本節(jié)點(diǎn)中所查詢到的數(shù)據(jù)與在主節(jié)點(diǎn)中所查詢到的數(shù)據(jù)是一致的,即日志記錄必須保證在副本節(jié)點(diǎn)中可見順序與主節(jié)點(diǎn)中提交順序是一致的.為了保證數(shù)據(jù)一致性,TPLR 中為每個(gè)表維護(hù)唯一的事務(wù)提交日志隊(duì)列,并通過串行回放事務(wù)提交日志隊(duì)列來保證副本節(jié)點(diǎn)與主節(jié)點(diǎn)中的每個(gè)表的事務(wù)提交順序一致.
日志并行回放具體可以分為回放和提交兩個(gè)階段.第一階段,回放線程并行回放所有的日志記錄,并更新到副本節(jié)點(diǎn)中,但此時(shí)數(shù)據(jù)對(duì)查詢操作不可見.第二階段,事務(wù)提交日志滿足提交條件時(shí)完成提交,即實(shí)現(xiàn)數(shù)據(jù)記錄對(duì)查詢操作可見.
第一階段,具體流程可以分為以下3 步.
(1) 回放線程從所對(duì)應(yīng)的日志記錄隊(duì)列中彈出日志記錄并完成解析.
(2) 回放線程根據(jù)日志記錄解析出的信息,在副本節(jié)點(diǎn)中查找該日志記錄所修改的數(shù)據(jù)記錄.
(3) 如果在 (2) 中查找為空,就將日志解析出的數(shù)據(jù)記錄作為新紀(jì)錄創(chuàng)建并插入,直接更新到數(shù)據(jù)表中.如果在 (2) 中查找不為空,說明數(shù)據(jù)記錄不是第一次創(chuàng)建,需要將其與舊版本數(shù)據(jù)記錄的行版本號(hào)進(jìn)行比較.如果行版本號(hào)是連續(xù)的,則可以將新數(shù)據(jù)記錄更新到所對(duì)應(yīng)的版本鏈中;如果行版本號(hào)不連續(xù),則需要等待行版本號(hào)更早的日志回放.
第二階段執(zhí)行過程展示在算法1 中.首先,回放線程會(huì)從事務(wù)提交日志隊(duì)列隊(duì)頭中獲取事務(wù)提交日志記錄,解析日志獲取事務(wù)號(hào)和提交時(shí)間戳.執(zhí)行完第一階段,事務(wù)DML 操作數(shù)d為0 時(shí),說明日志回放完成,達(dá)成了提交條件,可以將該提交日志從隊(duì)列中彈出,并對(duì)事務(wù)的NTT 值執(zhí)行減1 操作.當(dāng)事務(wù)處理表數(shù)n為0 時(shí),更新當(dāng)前表中已提交的事務(wù)最大提交時(shí)間戳.此時(shí),該事務(wù)完成提交,其所對(duì)應(yīng)的數(shù)據(jù)記錄對(duì)副本節(jié)點(diǎn)中的查詢操作可見.
當(dāng)數(shù)據(jù)表在OLAP 端和OLTP 端都被標(biāo)識(shí)為高頻時(shí),回放算法會(huì)因?yàn)閮?yōu)先傳送機(jī)制產(chǎn)生嚴(yán)重的數(shù)據(jù)傾斜問題.解決這一問題的主要思路是,在并行日志回放過程中,對(duì)每個(gè)表所對(duì)應(yīng)的回放線程資源隨著負(fù)載變化進(jìn)行動(dòng)態(tài)調(diào)整.特別需要說明的是,不能簡(jiǎn)單根據(jù)高頻查詢表分類,提前確定線程資源分配比例,因?yàn)楦哳l查詢表不一定是OLTP 端的高頻更新表,提前確定線程資源分配比例容易造成線程資源浪費(fèi).
本文將回放隊(duì)列的回放線程數(shù)量與其所對(duì)應(yīng)表待處理日志記錄數(shù)據(jù)總量設(shè)置為正相關(guān).當(dāng)主節(jié)點(diǎn)中的工作負(fù)載發(fā)生變化時(shí),每個(gè)表的更新情況也可能發(fā)生變化,積壓的待處理日志記錄數(shù)據(jù)量也會(huì)變化,在副本節(jié)點(diǎn)中也需要重新組織分配每個(gè)表的線程資源.因此,為了更合理地為每個(gè)表分配回放線程資源,通過以下公式來計(jì)算負(fù)責(zé)每個(gè)表所對(duì)應(yīng)的日志記錄的回放線程數(shù).
上式中:li(或lj)為表i(或j) 所對(duì)應(yīng)的日志記錄待處理數(shù)據(jù)總量,ti(或tj)為表i(或j)所對(duì)應(yīng)的回放線程數(shù)量,st表示回放線程總數(shù).式 (1) 表示任意兩個(gè)表的日志記錄數(shù)據(jù)總量與其所對(duì)應(yīng)的回放線程數(shù)量的比值是相等的,即每個(gè)回放線程負(fù)責(zé)回放的日志記錄數(shù)據(jù)量是相同的.
在引入優(yōu)先級(jí)日志發(fā)送后,日志本身可能不再是順序的,為了保證查詢服務(wù)的正確性,需要設(shè)計(jì)新機(jī)制,保證副本節(jié)點(diǎn)中行記錄更新次序和事務(wù)提交順序與主節(jié)點(diǎn)一致.
傳統(tǒng)以事務(wù)為粒度的并行回放算法的沖突檢測(cè),一般要先分析和建立事務(wù)之間的依賴關(guān)系,只有不存在依賴關(guān)系的事務(wù)才能并行執(zhí)行.這種處理方式主要存在兩個(gè)問題: ①事務(wù)依賴關(guān)系的分析需要消耗額外系統(tǒng)資源;② 整體并行度較低,因?yàn)槭聞?wù)沖突的本質(zhì)原因是不同的事務(wù)修改了同一條數(shù)據(jù)記錄,然而事務(wù)中的其他日志記錄可能并不存在沖突,理論上是可以并行回放的.
本文將日志并行過程的沖突問題轉(zhuǎn)化為序列化問題.在回放過程中,如果發(fā)現(xiàn)待修改的行記錄的版本號(hào)與當(dāng)前日志記錄中的行版本號(hào)不連續(xù),必然存在其他線程正在回放行記錄的早期版本,因此,需要等待其他線程完成回放,以保證行記錄更新的有序性.圖4 為并行日志回放沖突示例.
圖4 并行日志回放沖突示例Fig.4 Parallel log replay conflicts
主節(jié)點(diǎn)中的模擬行記錄經(jīng)歷3 個(gè)事務(wù)處理產(chǎn)生了3 個(gè)版本,并通過版本號(hào)標(biāo)識(shí)更新順序.主節(jié)點(diǎn)中記錄值最初為a,順序更新為b和c后分別產(chǎn)生了兩個(gè)新版本.對(duì)應(yīng)產(chǎn)生一條插入日志L1和兩條更新日志L10,L20.在圖4 中將傳輸?shù)娜罩居涗洷硎緸槿罩久词聞?wù)號(hào),記錄值,行版本號(hào),日志其他信息〉,可以看到已經(jīng)傳輸了L1,L10,L20共3 條日志.副本節(jié)點(diǎn)通過日志調(diào)度器將日志分配到所對(duì)應(yīng)的日志隊(duì)列中進(jìn)行回放.在回放L1日志時(shí)發(fā)現(xiàn)行版本號(hào)為1,即初始版本號(hào),因此,不需要進(jìn)行行版本號(hào)判斷,可以立即執(zhí)行.對(duì)于L10,L20,假設(shè)L20日志先解析完畢,被調(diào)度線程進(jìn)行回放.回放線程發(fā)現(xiàn)L20所對(duì)應(yīng)的行版本號(hào)是3,此時(shí)副本節(jié)點(diǎn)中該數(shù)據(jù)記錄的最新行版本號(hào)是1,兩個(gè)行版本號(hào)不連續(xù),這說明行版本號(hào)為 2 的日志記錄還未完成回放,此時(shí)日志記錄L20需要等待日志記錄L10回放完成后,才能繼續(xù)回放.綜上所述,通過將行更新操作序列化,解決了并行更新行產(chǎn)生的寫寫沖突,日志回放的粒度也能從事務(wù)級(jí)別細(xì)化到行級(jí)別.
硬件環(huán)境: 本系統(tǒng)部署在單個(gè)物理節(jié)點(diǎn)上,該節(jié)點(diǎn)含有1 個(gè)CPU (Central Processing Unit),型號(hào)為Intel Xeon Processor (Cascadelake) @2.9 GHz 32 核;內(nèi)存為128 GB;操作系統(tǒng)為64 位CentOS Linux release 8.2.
測(cè)試負(fù)載: 本文使用OLTP-Bench 工作負(fù)載生成工具生成TPC-C 負(fù)載來模擬現(xiàn)實(shí)業(yè)務(wù)場(chǎng)景,并以MySQL 為OLTP 端生成行級(jí)日志.TPC-C 包含 New-Order、Payment、Delivery 3 種讀寫事務(wù).在具體的實(shí)驗(yàn)中,為了模擬不同工作負(fù)載的變化,在實(shí)驗(yàn)中設(shè)置了4 種不同事務(wù)比例的工作負(fù)載.工作負(fù)載TPCC?1,事務(wù)New-Order、Payment 和 Delivery 的比例是 1∶1∶1,此時(shí)DML 操作涉及8 個(gè)表.工作負(fù)載 TPCC?2 中只有事務(wù) New-Order 和Deliery 的比例為1∶1,DML 操作涉及6 個(gè)表.工作負(fù)載 TPCC?3 中只有事務(wù) New-Order 和Payment 的比例為1∶1,DML 操作涉及8 個(gè)表.工作負(fù)載TPCC?4 中只有事務(wù) Delivery 和Payment 的比例為1∶1,DML 操作涉及7 個(gè)表.同時(shí)實(shí)驗(yàn)選擇ORDER-LINE 表作為高頻查詢表,因?yàn)?該表在所有測(cè)試工作負(fù)載中都有涉及,并且總DML 日志數(shù)也是所有表中最多的.
本文共設(shè)計(jì)4 種不同的日志回放方法,互為對(duì)照.方法1 用TPLR 表示,使用本文設(shè)計(jì)的TPLR方法進(jìn)行測(cè)試.方法2 用MLR (MySQL Log Replay)表示,使用MySQL 原生的日志并行回放方法進(jìn)行測(cè)試.方法3 用TPLR_avg 表示,設(shè)計(jì)為在TPLR 方法的基礎(chǔ)上將所有表設(shè)為同等的優(yōu)先級(jí).方法4用TPLR_Nodynamic 表示,設(shè)計(jì)為在TPLR 方法的基礎(chǔ)上將線程分配固定為平均值.
第一組的實(shí)驗(yàn)?zāi)康氖峭ㄟ^對(duì)比MLR、TPLR_avg、TPLR_Nodynamic 和TPLR 4 種方法在回放相同工作負(fù)載生成的高頻查詢表日志所需的時(shí)間,分析在不同方法中,高頻查詢表的數(shù)據(jù)同步效率.首先,通過OLTP 端執(zhí)行事務(wù)并生成所對(duì)應(yīng)的日志記錄;然后,統(tǒng)計(jì)4 個(gè)實(shí)驗(yàn)組對(duì)日志回放所需的時(shí)間.4 種工作負(fù)載TPCC-1 (圖5(a))、TPCC-2 (圖5(b))、TPCC-3 (圖5(c))、TPCC-4 (圖5(d))在不同方法上測(cè)試得到的回放時(shí)間.
通過觀察圖5 中的對(duì)比實(shí)驗(yàn)可以發(fā)現(xiàn),在不同的工作負(fù)載下,隨著日志記錄數(shù)據(jù)量的增長(zhǎng),TPLR 方法均能比MLR 和TPLR_avg 方法更快回放完高頻查詢表的日志.同時(shí)要特別說明,與TPLR 相比,其他兩種回放算法在高頻查詢表日志記錄位于日志末尾時(shí),需要回放所有日志數(shù)據(jù).
圖5 回放時(shí)間對(duì)比Fig.5 Comparison of replay time
從MLR 和TPLR_avg 的實(shí)驗(yàn)結(jié)果能看出,在4 種工作負(fù)載下TPLR_avg 日志回放時(shí)間都比MLR更短,即使沒有針對(duì)性回放,基于Table-ID 分組的日志并行回放方法的性能仍然是比較有競(jìng)爭(zhēng)力的.主要原因是基于Table-ID 對(duì)日志分組回放沖突概率較低,并行度較高,能發(fā)揮多核架構(gòu)性能優(yōu)勢(shì).
與TPLR 方法相比,TPLR_Nodynamic 的回放時(shí)間較長(zhǎng),因?yàn)槊總€(gè)表待回放日志數(shù)量不同,平均分配線程后,每個(gè)表所對(duì)應(yīng)工作線程回放完成時(shí)間也不同,導(dǎo)致部分回放線程閑置.與平均分配線程的方法不同,動(dòng)態(tài)分配方法對(duì)于日志記錄數(shù)據(jù)量較多的表,將分配更多的回放線程資源,日志記錄數(shù)據(jù)量較少的表則分配較少的回放線程資源,避免因?yàn)榈却罩居涗涊^多的表,而影響事務(wù)的提交.
對(duì)于實(shí)時(shí)性要求比較高的查詢分析操作,數(shù)據(jù)新鮮度對(duì)實(shí)時(shí)查詢分析操作的結(jié)果以及響應(yīng)時(shí)延有著非常重要的影響.本文對(duì)HTAP 系統(tǒng)的數(shù)據(jù)同步過程進(jìn)行優(yōu)化的一個(gè)重要目的就是提高副本節(jié)點(diǎn)中的數(shù)據(jù)新鮮度,因此,本節(jié)將通過相關(guān)實(shí)驗(yàn)比較不同方法下副本節(jié)點(diǎn)中的數(shù)據(jù)新鮮度.在相同時(shí)間下,副本節(jié)點(diǎn)中的數(shù)據(jù)版本越高,說明副本節(jié)點(diǎn)中的數(shù)據(jù)新鮮度越高.在具體實(shí)驗(yàn)中,為了有效判斷副本節(jié)點(diǎn)中的數(shù)據(jù)新鮮度,先通過每隔一段時(shí)間獲取一次已提交事務(wù)數(shù)量的方式來判斷副本節(jié)點(diǎn)中的數(shù)據(jù)新鮮度,再通過相同時(shí)間下事務(wù)提交的數(shù)量比較不同方法下副本節(jié)點(diǎn)中的數(shù)據(jù)新鮮度.這里特別說明,通過事務(wù)提交數(shù)判斷數(shù)據(jù)版本的前提是,回放日志已經(jīng)將不修改數(shù)據(jù)的事務(wù)過濾掉了,不會(huì)出現(xiàn)提交事務(wù)之后數(shù)據(jù)本身并未發(fā)生改變這種干擾統(tǒng)計(jì)準(zhǔn)確性的情況.
圖6 展示了TPLR 方法和MLR 方法所對(duì)應(yīng)的數(shù)據(jù)新鮮度變化.從圖6 中可以發(fā)現(xiàn),與MLR 方法相比,TPLR 方法能夠持續(xù)保證高頻查詢表擁有更高的數(shù)據(jù)新鮮度.TPLR 和MLR 的高頻查詢表的數(shù)據(jù)新鮮度差距隨著時(shí)間推移不斷增大.從實(shí)驗(yàn)結(jié)果可以看出,TPLR 方法比MLR 方法多出的預(yù)處理操作耗時(shí)對(duì)回放效率影響不大.同時(shí),因?yàn)椴⑿谢胤哦氲氖聞?wù)提交隊(duì)列,在實(shí)驗(yàn)過程中并不是一個(gè)瓶頸,只要DML 日志記錄之間沒有產(chǎn)生沖突,事務(wù)的提交就不會(huì)影響到日志的回放速度.
圖6 數(shù)據(jù)新鮮度對(duì)比Fig.6 Comparison of data freshness
在HTAP 解耦存儲(chǔ)架構(gòu)下,OLAP 端需要更有針對(duì)性、更高效的方法來同步OLTP 端數(shù)據(jù),以保證數(shù)據(jù)新鮮度能達(dá)到實(shí)時(shí)數(shù)據(jù)分析的要求.本文根據(jù)OLAP 端的查詢統(tǒng)計(jì)數(shù)據(jù),將表分為高頻查詢表和低頻查詢表.基于統(tǒng)計(jì)好的查詢頻率,在OLTP 端傳送日志數(shù)據(jù)時(shí),TPLR 會(huì)調(diào)整日志發(fā)送的優(yōu)先級(jí),提升高頻查詢表的發(fā)送速度.同時(shí),在OLAP 端,TPLR 使用基于表分組的日志并行回放方法,對(duì)回放隊(duì)列針對(duì)性傾斜線程資源.最后,通過實(shí)驗(yàn)證明,與傳統(tǒng)的基于日志的數(shù)據(jù)同步方法相比,本文所提出的數(shù)據(jù)同步方法針對(duì)HTAP 負(fù)載特點(diǎn)進(jìn)行優(yōu)化,保證了更高的數(shù)據(jù)新鮮度.