1月11日,騰訊云TDSQL PG開源版(開源代號TBase)再升級:分布區(qū)表關聯查詢性能(join)提升超10倍,同時提升了產品在分布式場景下的易用性,增加靈活可用的功能組件。
該升級版本在第十一屆PostgreSQL中國技術大會上正式公布,同時更新文檔已同步在GitHub上。依托社區(qū)和內部業(yè)務系統的實踐檢驗,TDSQL PG開源版基本保持每月一次小升級、每半年一次重大升級的節(jié)奏,助力眾多開發(fā)者應用前沿數據庫技術。
本期將為大家深度解讀TDSQL PG開源版升級特性,具體包括:分區(qū)表功能增強、異地多活易用性增強、分布式死鎖自動檢測并解鎖功能、2PC殘留自動檢測并清理功能等硬核干貨。
TDSQL PG版(原名TBase)是騰訊自主研發(fā)的新一代分布式國產數據庫,其具備業(yè)界領先的HTAP能力,屬于MPP無共享架構,在企業(yè)級安全方面采用三權分立安全體系。? ? ? ??
2020年,騰訊云正式宣布數據庫品牌TDSQL的全新戰(zhàn)略升級計劃。原有的TDSQL、TBase、CynosDB三大產品線統一升級為“騰訊云企業(yè)級分布式數據庫TDSQL”。全新升級后的騰訊云TDSQL涵蓋分布式、分析型、云原生等多引擎融合的完整數據庫產品體系。TDSQL PG版則是TDSQL系列產品之一,主要針對HTAP場景。
下圖是TDSQL PG版的總體框架。左上角為事務管理器GTM,負責整個集群的事務管理和全局事務的協調。右上角為協調節(jié)點CN,它是業(yè)務應用訪問的入口,每個節(jié)點對等,業(yè)務連接任意節(jié)點,最終返回的數據都相同。右下角為數據節(jié)點DN,每個DN只存儲部分用戶數據,所有DN一起組成完整的數據集。最左邊和最下邊的部分屬于管控系統,負責系統的資源管理和告警監(jiān)控。??
? ? ? ?
? ? ? ? ?
TDSQL PG版最早可追溯到2008年,2012年其發(fā)布第一個分布式版本,2015年其發(fā)布第二個分布式版本。截至目前,TDSQL PG版已經在眾多市場客戶中得到應用,包括數字廣東、云南公安、微信廣告、微信支付等。值得一提的是,TDSQL PG版在2019年中標PICC,成為行業(yè)內第一個成功落地保險核心系統的分布式國產數據庫。?
TDSQL PG版在2019年11月7日正式宣布開源。開源地址在Github平臺上,下圖是供廣大開發(fā)人員使用參考文檔的wiki地址。
? ? ? ?
? ? ? ? ?
TDSQL PG版開源對用戶有重要價值,分別體現在:
- 版本經過大量業(yè)務驗證,成熟穩(wěn)定,開源版本和騰訊自用版本共基線,能夠幫助用戶快速構建核心業(yè)務。
- 同時支持OLTP/OLAP能力,提供一站式數據庫解決方案。
- 安全可控的企業(yè)級分布式數據庫能力,騰訊專業(yè)研發(fā)運營團隊持續(xù)投入開發(fā)和維護,推動社區(qū)進步。
- 團隊積極回饋開源社區(qū),即時響應用戶需求,努力創(chuàng)造開源社會價值。
2021年7月,我們進行了TDSQL PG版 2.2.0版本的升級。2.2.0升級主要包括四個方面:內存管理優(yōu)化,提供會話內存視圖,進行優(yōu)化管理;優(yōu)化分布式執(zhí)行器、優(yōu)化器;分布式調優(yōu)性能增強;分布式執(zhí)行可視化能力增強。
? ? ? ?
? ? ? ? ?2.1 執(zhí)行器/優(yōu)化器優(yōu)化
我們將子查詢在內部優(yōu)化成一個關聯查詢,提高查詢效率。以視圖中的表格為例,需要根據表A中的ID找到表B中每一條對應ID的數據,再用表A的值與表B中值的MIN進行比較。在優(yōu)化前,因為這是一個子查詢,假如表A有1000條記錄,則A中每一條記錄都要在表B進行全量掃描。做完這個查詢至少要將表B掃描一千次,這樣做的成本非常高。在優(yōu)化后,因為表B需要取B的MIN最小值,且我們需要利用id做join,所以可以先掃描一遍B表,根據id先進行聚集,把每一個id最小的MIN值取出來,生成聚集表,最后聚集表與表A進行hash join,因此我們只需將B表進行一次掃描即可。
? ? ? ?
? ? ? ? ?我們還對distinct進行性能優(yōu)化。在優(yōu)化前,需要將所有數據從DN節(jié)點拉到CN節(jié)點,由CN節(jié)點進行distinct的去重操作。因為分布式系統數據量特別大,如果全部拉到CN,會導致數據量大,網絡負載高,CN也會成為單點瓶頸,難以發(fā)揮分布式特性。我們針對此類情況進行優(yōu)化。先在DN本地進行部分的distinct去重,使得每個DN可以并行計算,并行后將結果全部發(fā)到CN上,由CN進行最終的去重操作,減少了大量的網絡交互,充分發(fā)揮出分布式數據庫的特性。
? ? ? ?
? ? ? ? ?在對優(yōu)化器進行優(yōu)化后,我們取部分TPCDS標準測試集進行測試,發(fā)現有些SQL的性能可以提升上千倍。
? ? ? ?
? ? ? ? ?2.2 內存管理優(yōu)化
我們提供Memory的內存視圖詳情,能夠詳細看到每一個進程占用的內存情況。除了對視圖進行增強外,我們還對內存使用進行詳細優(yōu)化。
? ? ? ?
? ? ? ? ?下圖展示的是假設有一個用戶連接,這個連接在訪問一萬張表后的內存占用情況(訪問完該連接還沒有退出、仍處于空閑狀態(tài)時的內存占用情況)。從下表中可以看到,TopMemoryContext上出現數量級增長,實現10倍以上提升,CacheMemoryContext也實現20倍的提升。? ? ??
? ? ? ? ?針對明顯空閑的連接卻占用大量內存的不合理情況,我們進行了優(yōu)化。我們將內存的使用分為兩部分:第一部分是RelCache,即用戶數據表的Cache;第二部分是Cat Cache,即元數據的Cache。如果需要對某個Rel進行Cache,我們會將新來的項放在Relation LRU List的最前面,此后每次來新的項我們都往前面加。當LRU項目超過預定意義的參數時,我們會從后往前去遍歷LRU,將引用計數為0的Relation的內存項釋放掉。Cat LRU元數據緩存也同理,我們將新來的某條元數據緩存,將其放在Cat LRU List的最前面,再從后往前進行遍歷,將引用計數為0的項進行刪除,從而釋放內存。由此可以將部分占用內存大且低頻使用的空閑連接,通過LRU將其替換出去,使會話內存減少55.7%。
? ? ? ?
? ? ? ? ?對于分布式系統,除了單點外還要考慮分布式內存管理。當一個應用程序連接到CN后,CN需要跟DN進行數據通信。但它與DN的通信的DN進程需要向本地的Pooler申請連接,Pooler會將本地緩存的部分到DN的空閑連接分配給CN,此后CN才能與DN進行通信。Pooler本地緩存了很多到DN的空閑連接,實時準備為CN提供服務,以至于存在許多空閑連接。對此,我們在Pooler內部上線實時檢測空閑連接的功能,將大于配置參數的連接釋放掉,使得空閑連接占用減少89.3%。
? ? ? ?
? ? ? ? ?經過優(yōu)化后,在2CN、2DN的情況下,依舊是一個連接在訪問一萬張表后的內存占用情況,優(yōu)化前總內存占51.4M,經優(yōu)化后只占5.4M。節(jié)點內部DN自動釋放空閑連接,空閑連接直接減少89%,經過RelCache LRU替換后,CN連接內存減少55%。? ? ? ?
? ? ? ? ?2.3 分布式執(zhí)行可視化
以下圖為例,表A和表B進行join,A表作為分布鍵,B表作為非分布鍵,我們進行join時要將join的過程下推到DN節(jié)點執(zhí)行,但因為表B不是分布鍵join,所以需要對表B按f2字段進行重分布。在重分布過程中,DN1上有一個backend進程,需要掃描本地的表B,把掃描到的部分數據留給本地的DN節(jié)點,部分數據則重分布到DN2數據節(jié)點。所以一次重分布中,本地會新創(chuàng)建一個DN1的backend進程進行數據掃描,還要創(chuàng)建另一個backend進程負責發(fā)送數據給DN2。? ? ??
? ? ? ? ?利用分布式可視化的能力,可以查到任意一個用戶的session id,查到session id后,可以根據session id查到對應的在不同CN、DN上的各個進程目前在做什么。比如這個節(jié)點我們需要做hash join,因為需要根據f2字段做數據重分布,現在在等待重分布的數據,另外一個進程是掃描表B,掃描完后會提供給前面的進程,才能進行hash join,CN1則是在執(zhí)行查詢事務。通過分布式執(zhí)行過程的可視化視圖,我們可以詳細知道一個SQL下去各個節(jié)點在做什么。
? ? ? ?
? ? ? ? ?下圖展示的是分布式可視化功能的使用方法,詳情可參考Github上的wiki地址:? ? ?
? ? ? ? ?
TDSQL PG開源版此次升級V2.3.0版本包括四個方面:分區(qū)表能力增強、異地多活易用性增強、分布式死鎖檢測、2PC殘留自動清理。? ? ? ?
? ? ? ? ?3.1 分區(qū)表能力增強
針對分區(qū)表能力,本次TDSQL PG版升級,整體響應速度更快,有效應對此前業(yè)界仍然面臨數據量大時讀寫性能慢等問題。新版本通過分區(qū)表功能增強,包括增加hash分區(qū)類型、支持default分區(qū)子表創(chuàng)建、分區(qū)父表索引操作自動同步子表等,實現分區(qū)表便捷管理;同時,新版本實現了分區(qū)剪枝性能提升30%,分布區(qū)表關聯查詢性能(join)提升超10倍,完美解決查詢效率問題。具體來說,在原有支持range和list分區(qū)表的基礎上,TDSQL PG版新增hash分區(qū)表功能。用戶在創(chuàng)建時可以指定該分區(qū)表為hash分區(qū)表,再指定分區(qū)鍵,同時需要指定hash模數和余數。TDSQL PG版還新增了default分區(qū)。在上一版本中,在創(chuàng)建分區(qū)表且創(chuàng)建子分區(qū)時,如果沒有創(chuàng)建default默認分區(qū),用戶插入數據時,如果插入不屬于指定分區(qū)的其他數據,會出現報錯。在本次升級后,如果插入的數據不屬于其他指定子分區(qū),所有數據會落到default分區(qū)。比如下圖右邊的例子,2019年12月和2020年3月的數據,都不屬于指定的其他子分區(qū),因此會落入default分區(qū)。其優(yōu)點是不需要報錯,同時必要時可以查詢不屬于指定分區(qū)的其他零散值。該功能目前僅支持range和list分區(qū),不支持hash分區(qū)。因為在指定hash的模數和余數后,數據就必然會落在指定分區(qū),不存在不屬于指定分區(qū)的情況。? ? ??
? ? ? ? ?TDSQL PG版也支持分區(qū)鍵更新。在上一版本中,如果要更新創(chuàng)建表時指定的分區(qū)鍵,就會出現報錯,不允許更新。新版本對此進行升級。在下圖左邊的例子中,一個分區(qū)子表存儲0到30的數據,另一個分區(qū)子表存儲30到60的數據,用戶可以對分區(qū)鍵即id鍵進行更新,將id從25改為50,數據會自動從原來的分區(qū)轉移到新的分區(qū)。此外,TDSQL PG版還支持分區(qū)父表建索引自動同步子表。在上一版本中,如果要為分區(qū)表建索引,只能給某個指定子表建分區(qū),不能給父表建分區(qū)。在新版本中,我們對此進行優(yōu)化,支持在父表上指定建分區(qū)。在下圖右邊的例子中,假設要給tbl表的id字段建索引,在創(chuàng)建后它會自動將索引同步到所有子分區(qū)上,比如2020年1月分區(qū)、2020年2月分區(qū)和default分區(qū)。用戶只需要在父表上執(zhí)行一條SQL,它就會自動在所有子分區(qū)上全部創(chuàng)建該索引,其優(yōu)點是方便用戶對分區(qū)里的索引進行維護。我們也支持創(chuàng)建唯一分區(qū),但需要包含分區(qū)鍵。
? ? ? ?
? ? ? ? ?除了分區(qū)能力的增強,TDSQL PG版還引入partition-wise join,對原有性能進行提升。假設有兩個分區(qū)表,分別為A表和B表,它們的分區(qū)數量完全相同,且分區(qū)的字段類型一致。如果沒有partition-wise join,在進行join時,需要先將A表中所有子分區(qū)的數據全部撈取,再將B表中所有子分區(qū)的數據全部撈取,再用A表全量數據與B表全量數據進行join,這種操作方式的數據量非常大。在引入partition-wise join后,因為兩個分區(qū)鍵為同一類型,且分區(qū)數量相同,我們可以將A表的分區(qū)1與B表的分區(qū)1進行join,A表的分區(qū)2與B表的分區(qū)2進行join。我們并不需要將A表的全量數據與B表的全量數據進行join,只需要將對等的分區(qū)進行join即可,從而使性能得到大幅提升。下圖是該功能實際效果的測試對比。在partition-wise join打開的情況下,與上一版本相比,最新版本的性能有10倍的提升。
? ? ? ?
? ? ? ? ?3.2 異地多活的易用性增強
另一重要升級,是異地多活的易用性增強。原先單活時跨區(qū)接入延時大,一旦發(fā)生故障服務和數據庫都需要切換,流程復雜;而異地多中心接入時延小,業(yè)務在一個中心內能完成閉環(huán),秒級即可完成切換。本次升級新增多活插件化功能,方便用戶安裝配置,提升了產品易用性。異地多活主要區(qū)別于傳統兩地三中心的單活模式。在單活模式中,假設主庫在南方,北方的服務要寫入主庫,因為地域相隔太遠,延時會非常大。如果出現南北網絡故障,北方用戶就無法訪問主庫,出現不可用情況。如果采用異地多活模式則不存在上述問題。我們可以在北方多設立一個主庫,北方的服務寫入北方主庫,南方的服務寫入南方主庫,南北主庫之間進行雙向復制。其優(yōu)點在于南北主庫各自都有全量數據集,且業(yè)務可以就近接入,在一個中心內部實現閉環(huán),即使南北出現網絡故障也不會影響服務。
? ? ? ?
? ? ? ? ?異地多活采用雙向復制功能,下圖是異地多活架構示意圖。區(qū)域1是深圳,區(qū)域2是上海,我們將區(qū)域1的數據節(jié)點作為發(fā)布端,將區(qū)域2的CN節(jié)點作為訂閱端(CN可以訂閱作為發(fā)布端的數據節(jié)點上的數據),在完成數據訂閱后,CN需要經過一個路由才能將訂閱到的數據寫入本地的DN節(jié)點上,這樣我們支持了異構集群之間的同步,一個CN可以訂閱多個數據節(jié)點。
? ? ? ?
? ? ? ? ?在新版本中,我們對易用性進行增強。通過tbase_subscription工具,用戶可以利用SQL直接創(chuàng)建整個同步的異地多活過程。創(chuàng)建時還可以指定訂閱的并行度,從而提高訂閱效率。此外,因為一個CN可以訂閱多個DN,用戶可以將訂閱任務下發(fā)到不同CN上,使CN進行負載均衡。
? ? ? ?
? ? ? ? ?3.3 分布式死鎖自動檢測
以下圖為例。假設有兩個CN,分別為CN1和CN2。有兩個用戶,用戶1連到CN1,產生一個session,用戶2連到CN2,也產生一個session。用戶1使用顯示事務查詢A表數據,用戶2也采用顯示事務查詢B表數據。用戶1查詢完A表數據時,想將B表進行刪除。因為是分布式系統,CN2上也存在B表,需要同步進行刪除。如果要刪除B表則需要B表的排他鎖。但這時在CN2上,用戶2剛啟動顯示事務查詢B表,獲得B表的共享鎖,這就產生了鎖沖突,反之亦然。在這種情況下,CN1有A表的共享鎖,需要等B表的排他鎖,CN2有B表的共享鎖,又要等A表的排他鎖,兩個事務之間就形成了分布式死鎖。
? ? ? ?
? ? ? ? ?針對這種情況,我們引入了pg_unlock工具。該工具可通過extension安裝,快速便捷。用戶安裝后可以查到分布式死鎖之間的依賴關系。比如在上面的例子中,CN1是一個依賴于CN2的事務,CN2是一個依賴于CN1的事務。用戶還可以查到集群中一個死鎖的詳細信息。比如CN1上的drop b需要B表的排他鎖,CN2上的drop a也需要A的排他鎖,它們之間都是求而不得存在死鎖。我們可以通過執(zhí)行pg_unlock execute來解開死鎖,解開的方法是回滾掉一個事務。在回滾事務時,我們會在內部進行優(yōu)化,計算出回滾代價最小的事務并進行回滾。
? ? ? ?
? ? ? ? ?3.4 2PC殘留自動清理
以下圖為例,假設有兩個CN,分別為CN1、CN2,有兩個DN,分別為DN1、DN2。用戶連進來創(chuàng)建A表,再進行prepare transaction,該事務命名為create a。我們通過另一個CN連接進來,可以查詢處于prepare狀態(tài)的事務有哪些,可以看到CN1上有一個prepare事務叫create a,CN2、DN1、DN2也有。用戶繼續(xù)執(zhí)行在DN2上將create a事務進行回滾的操作,此后該操作會話直接退出。退出后我們再去查處于prepare狀態(tài)的事務,發(fā)現CN1、CN2、DN1各有一個create a事務,但DN2上沒有。因為上述會話在退出前,對DN2上的create a事務進行回滾,相當于該事務不存在prepare狀態(tài)。由于會話已經退出,該事務永遠不會終止,就出現了2PC殘留的情況。
? ? ? ?
? ? ? ? ?針對這種情況,我們引入了pg-clean工具。通過pg_clean check transaction,用戶可以直接查到目前有哪些2PC殘留事務,以及這些事務的名稱、參與的節(jié)點等。通過pg_clean execute,我們可以對2PC殘留事務進行自動清理。這實際上是將殘留事務進行abort操作。因為CN1、CN2、DN1上的事務都處于prepare狀態(tài),但DN2上執(zhí)行了abort,它只能將該事務abort,不能將其提交,否則會出現部分提交數據不一致的問題。我們能夠根據事務狀態(tài)自動選擇回滾或提交,從而將2PC殘留事務進行清理。
? ? ? ?
? ? ? ? ?
TDSQL PG版
開源生態(tài)未來發(fā)展計劃
在下個版本中,我們計劃在以下四個方面對TDSQL PG開源版進行加強:- 存儲能力加強。支持透明壓縮,減少磁盤存儲成本;提供Direct IO能力,提高某些情況下的寫效率。
- 索引優(yōu)化。支持全局索引,提升非分布鍵查詢性能。
- 優(yōu)化器能力提升。提高執(zhí)行效率,提升業(yè)務查詢及寫的性能。
- 分布式狀態(tài)可視化。優(yōu)化全局session可視化、query可視化、分布式鎖可視化、分布式事務狀態(tài)可視化,幫助用戶更好地掌控系統。
開源的本質是以技術開放促進技術創(chuàng)新。騰訊云對TDSQL PG版不斷開發(fā)和投入,版本經過大量業(yè)務驗證,成熟穩(wěn)定,開源版本和騰訊自用版本共基線,能夠幫助用戶快速構建核心業(yè)務,將持續(xù)給客戶帶來價值,與廣大開發(fā)者共同打造可持續(xù)的國產數據庫開源生態(tài)。同時歡迎各位感興趣的小伙伴,與我們一起共同助力國產數據庫技術創(chuàng)新與開源生態(tài)發(fā)展!