不知大家是否已經(jīng)留意到,在 TDengine 3.0 的官方文檔(https://docs.taosdata.com/taos-sql/show/#)中,有了這樣一個(gè)命令 :show transactions。顧名思義,這是“事務(wù)”。
在 Database 的語(yǔ)境中,滿足 ACID 屬性的數(shù)據(jù)庫(kù)操作序列即可稱為事務(wù),它是數(shù)據(jù)庫(kù)的一個(gè)不可拆分的工作單元,包含著一個(gè)數(shù)據(jù)庫(kù)操作的序列,這些操作要么全部執(zhí)行,要么全部不執(zhí)行。換個(gè)角度也可以說(shuō),事務(wù)是為了實(shí)現(xiàn) ACID 特性的一種工具。
不過(guò)在 TDengine 中,依托于“一個(gè)數(shù)據(jù)采集點(diǎn)一張表”的設(shè)計(jì)理念,針對(duì)表的操作都是以隊(duì)列方式逐個(gè)進(jìn)行的,所以在絕大多數(shù)情況下都不需要事務(wù)機(jī)制。那 TDengine 3.0 中的“事務(wù)”是用來(lái)解決什么問(wèn)題的呢?答案就是:3.0 中的事務(wù)機(jī)制并沒有應(yīng)用在業(yè)務(wù)數(shù)據(jù)上,而是針對(duì)數(shù)據(jù)庫(kù)的元數(shù)據(jù)的,它的目的是利用事務(wù)的 ACID 特性,來(lái)強(qiáng)化元數(shù)據(jù)的一致性,因此,普通用戶對(duì)此是無(wú)感知的,但是對(duì) TDengine 的運(yùn)維人員而言,意義會(huì)更大一些。
大家都知道 TDengine 3.0 是一款高性能、云原生的分布式時(shí)序數(shù)據(jù)庫(kù)(Time Series Database),甚至可以支持十億級(jí)別的表數(shù)量,因此它的元數(shù)據(jù)量是十分龐大的。那么如果使用了事務(wù),會(huì)不會(huì)影響 TDengine 的高性能呢?
這里就需要結(jié)合 TDengine 2.x 時(shí)代的元數(shù)據(jù)架構(gòu)來(lái)說(shuō)起了。
一、2.x 的元數(shù)據(jù)架構(gòu)
在 2.x 版本中,管理節(jié)點(diǎn) mnode 中的 sdb 模塊存儲(chǔ)了大量元數(shù)據(jù),如集群信息、用戶信息、數(shù)據(jù)庫(kù)信息、超級(jí)表信息以及普通表信息等。這些不同類型的信息,會(huì)在內(nèi)存中分別以一個(gè) hash 表的形式來(lái)維護(hù)。其中,一些元數(shù)據(jù)需要在管理節(jié)點(diǎn)(mnode)和數(shù)據(jù)節(jié)點(diǎn)(dnode/vnode)中分別存儲(chǔ),比如超級(jí)表、普通表。所以,當(dāng)對(duì)數(shù)據(jù)庫(kù)執(zhí)行 DDL 操作時(shí),需要在 mnode 上對(duì)這個(gè) hash 表操作一次,還要再去 dnode 中的 vnode 也做一次。這里為了性能的優(yōu)化,TDengine 選擇以異步的方式來(lái)完成操作。以刪表為例,當(dāng) mnode 內(nèi)存中的 hash 表刪掉了這個(gè)表后,會(huì)立即返回成功。后續(xù)由 dnode/vnode 一側(cè)刪除自己的元數(shù)據(jù),達(dá)成最終一致。
因?yàn)樵摿鞒痰姆菑?qiáng)一致性,可能會(huì)導(dǎo)致在某些極特殊情況下(比如網(wǎng)絡(luò)不穩(wěn)定),出現(xiàn) mnode 與 vnode 元數(shù)據(jù)不同步的情況(有的用戶遇到過(guò)這個(gè)錯(cuò)誤信息:“Invalid table id”)。但是如果為了強(qiáng)一致性而在 2.x 中引入事務(wù)機(jī)制,那么對(duì)于存在超大規(guī)模 DDL 操作的場(chǎng)景來(lái)說(shuō)(如刪除一張擁有百萬(wàn)千萬(wàn)子表的超級(jí)表),這種分布式的事務(wù)對(duì)數(shù)據(jù)庫(kù)的性能損耗又將非常之大。
那么應(yīng)該如何解決這個(gè)問(wèn)題呢?我們的思路是:利用“分布式事務(wù)”,解決 mnode 和 dnode 同步時(shí)的問(wèn)題,但是又不能讓其影響到數(shù)據(jù)庫(kù)的性能。
二、3.0 的事務(wù)引入
以此為依據(jù),TDengine 在 3.0 中選擇把開銷最大的普通表元數(shù)據(jù)從 mnode 中移除,完全只放在各個(gè) vnode 中分布式存儲(chǔ),這樣除了防止了上述 mnode 和 vnode 普通表元數(shù)據(jù)不一致的現(xiàn)象發(fā)生,更使得 TDengine 不再具有單點(diǎn)性能瓶頸,解決了業(yè)界的“高基數(shù)”難題,從而可以支持十億級(jí)別的時(shí)間線。在其余的元數(shù)據(jù)模塊中,我們則引入了事務(wù)機(jī)制,確保了這部分元數(shù)據(jù)的 ACID 特性。
下圖是一個(gè)兩階段提交的流程,其中 Coordinator(協(xié)調(diào)者)就是 mnode,而 Participants(參與者) 就是 dnode/vnode。
創(chuàng)建事務(wù)后,協(xié)調(diào)者本地準(zhǔn)備事務(wù)所需的必要數(shù)據(jù),redo、undo 日志等。然后向參與者們發(fā)送事務(wù)執(zhí)行請(qǐng)求,如果參與者們的事務(wù)執(zhí)行結(jié)果皆為成功,那么則進(jìn)入提交階段,由協(xié)調(diào)者提交事務(wù)。

需要注意的是:如果作為協(xié)調(diào)者的 mnode 宕機(jī),那么其他 mnode 在成為 leader 之后,會(huì)作為新的協(xié)調(diào)者繼續(xù)驅(qū)動(dòng)事務(wù)的執(zhí)行。也就是說(shuō),Raft 協(xié)議保證了事務(wù)的一致性和持久性。
在現(xiàn)在的 3.0 架構(gòu)中,為了避免不同的事務(wù)操作共享資源,管理節(jié)點(diǎn)針對(duì)不同類型的元數(shù)據(jù)把事務(wù)分成了幾個(gè)級(jí)別,分別為無(wú)沖突級(jí)別、全局級(jí)別、數(shù)據(jù)庫(kù)級(jí)別以及數(shù)據(jù)庫(kù)內(nèi)部級(jí)別。如果在內(nèi)存中仍有未完成且具有相同沖突類型的事務(wù),后執(zhí)行的事務(wù)將會(huì)等待前者執(zhí)行完畢再執(zhí)行。

最終,一個(gè)事務(wù)的運(yùn)行狀態(tài)與行為是由該類元數(shù)據(jù)本身的沖突級(jí)別和失敗策略等因素決定的,而這一切是對(duì)用戶無(wú)感知的。用戶只需知道事務(wù)在執(zhí)行階段具有 PREPARE,REDO_ACTION,COMMIT,COMMIT_ACTION,ROLLBACK,UNDO_ACTION,F(xiàn)INISHED 7 個(gè)階段。

其中,比較關(guān)鍵的地方是:在 PREPARE 階段,事務(wù)的基本信息在不同的 mnode 間達(dá)成一致;然后在 REDO_ACTION 階段,執(zhí)行 mnode 的本地操作、以及涉及的 vnode 的遠(yuǎn)端操作。當(dāng) REDO_ACTION 的所有操作都完成后,進(jìn)入 COMMIT 階段。注:REDO_ACTION 不止包含了第一次執(zhí)行任務(wù),還包括執(zhí)行失敗后的重做。COMMIT 階段則負(fù)責(zé)把數(shù)據(jù)最終寫入到 SDB 對(duì)應(yīng)的表中,完成持久化。在最后的 FINISHED 階段,清理 SDB 模塊中事務(wù)表的相關(guān)內(nèi)存,完成整個(gè)任務(wù)的執(zhí)行或者回滾。

通過(guò) show transactions,我們可以明確了解到當(dāng)前事務(wù)運(yùn)行的階段。除了確保數(shù)據(jù)庫(kù)的安全一致之外,也給了數(shù)據(jù)庫(kù)運(yùn)維人員更充足的信息去診斷數(shù)據(jù)庫(kù)的當(dāng)前狀態(tài)。不過(guò),在絕大多數(shù)時(shí)間,show transactions 的輸出是沒有結(jié)果的,因?yàn)樵獢?shù)據(jù)體量較小,所以執(zhí)行速度都非???。
總而言之,TDengine 3.0 的“事務(wù)”機(jī)制為集群信息、用戶信息、數(shù)據(jù)庫(kù)信息以及超級(jí)表信息等元數(shù)據(jù)帶來(lái)了 ACID 的特性保障。
而在它背后的把普通表元數(shù)據(jù)完全遷移到 vnode 的架構(gòu)變更,使得 TDengine 不再具有單點(diǎn)瓶頸,獲得了超強(qiáng)的水平擴(kuò)展能力,如果想獲得更多的數(shù)據(jù)處理能力,只需要加入更多的數(shù)據(jù)節(jié)點(diǎn)即可。
在下一篇文章中,我會(huì)繼續(xù)和大家分享該變更帶來(lái)的諸多優(yōu)勢(shì),一起感受 TDengine 這款開源、高性能、云原生的時(shí)序數(shù)據(jù)庫(kù)的架構(gòu)變化之路。

加入物聯(lián)網(wǎng)大數(shù)據(jù)交流群



互聯(lián)網(wǎng).png)



-1.png)




.png)


證.png)


伙伴.png)
伙伴.png)
伙伴.png)



