小 T 導讀:為(wei)什么我的集群(qun)數(shu)(shu)據(ju)分(fen)布得不均勻(yun)?這篇(pian)文(wen)章(zhang)就是為(wei)了解決這個問題(ti)而寫的。但即便(bian)是沒有遇到“TDengine集群(qun)數(shu)(shu)據(ju)不均勻(yun)分(fen)布”這個現象的用戶,我們也推薦一(yi)讀。因(yin)為(wei)可(ke)能(neng)你目(mu)前只是在(zai)通用場景(jing)(jing)下使(shi)用集群(qun),當一(yi)些特殊的場景(jing)(jing)出現時,深入地了解集群(qun)參數(shu)(shu)和數(shu)(shu)據(ju)庫(ku)架構原(yuan)理才會(hui)真正地讓你做到游刃有余。至于集群(qun)如何搭建并不是本文(wen)主題(ti),請嚴格根據(ju)官方文(wen)檔指示(shi)操作即可(ke)。官方文(wen)檔地址:
為了充分理解文章內容,首先大家一定要先了解vnode這個概念(nian)——每個 vnode 都是一(yi)個相對獨立的(de)(de)工作單(dan)元,是存(cun)儲(chu)時(shi)序(xu)數據(表)的(de)(de)基本單(dan)元,具(ju)有獨立的(de)(de)運行線程(cheng),內存(cun)空(kong)間與(yu)持久化存(cun)儲(chu)的(de)(de)路徑。如果覺得不夠清晰的(de)(de)話(hua),接著(zhu)往下讀,隨著(zhu)知識點的(de)(de)串(chuan)聯,或(huo)許您會(hui)豁然(ran)開朗起來(lai)(lai)。現(xian)在,我們來(lai)(lai)根據不同的(de)(de)場景給出具(ju)體分析:通(tong)常(chang)來(lai)(lai)說,數據分配不均勻(yun)有兩種(zhong)。
場景一:表分布不均勻
需要測(ce)試(shi)表數量很少的(de)(de)數據庫性能(neng)時比(bi)較容易(yi)發(fa)生這(zhe)個(ge)(ge)(ge)現象:你建了(le)1200張(zhang)表,但是卻發(fa)現有1000張(zhang)表都(dou)在同一(yi)個(ge)(ge)(ge)vnode里面,只有200張(zhang)表在另(ling)一(yi)個(ge)(ge)(ge)vnode里面。這(zhe)種場景的(de)(de)壞處是,大部分表都(dou)進入(ru)了(le)同一(yi)個(ge)(ge)(ge)vnode數據分布不均勻。此(ci)外還會導(dao)致只有兩個(ge)(ge)(ge)線程在為TDengine工作,因此(ci)無法利用計算(suan)機的(de)(de)多核(he)(假設你的(de)(de)服務器CPU是雙(shuang)核(he)以上),從而浪費了(le)TDengine的(de)(de)橫向擴展性。我先來(lai)簡單說說導(dao)致上述情(qing)況的(de)(de)原(yuan)因——在TDengine中有這(zhe)樣三個(ge)(ge)(ge)參數:
- maxVgroupsPerDb: 每個數據庫中能夠使用的最大vnode個數(單個副本),默認為0;
- minTablesPerVnode: 每個vnode中必須創建的最小表數,即是說這是第一輪建表用的步長(就是滿多少表寫下一個vnode),默認1000;
- tablelncStepPerVnode:每個vnode中超過最小表數后的遞增步長(即是后續滿多少表寫下一個vnode),默認1000。
在持續的(de)(de)建(jian)(jian)表(biao)(biao)過(guo)程(cheng)中(zhong),TDengine就是靠這(zhe)三個(ge)(ge)參數(shu)來控(kong)制(zhi)表(biao)(biao)的(de)(de)分布的(de)(de)。大家可以在使(shi)用(yong)taosdemo批量(liang)建(jian)(jian)表(biao)(biao)的(de)(de)時(shi)候(hou)觀察一(yi)(yi)(yi)下(xia):打開(kai)另一(yi)(yi)(yi)個(ge)(ge)taos窗口,在建(jian)(jian)表(biao)(biao)的(de)(de)時(shi)候(hou)一(yi)(yi)(yi)直輸(shu)入show vgroups命令,就能(neng)看到(dao)上述參數(shu)所控(kong)制(zhi)的(de)(de)建(jian)(jian)表(biao)(biao)過(guo)程(cheng)了:在第一(yi)(yi)(yi)個(ge)(ge)vnode中(zhong),表(biao)(biao)數(shu)量(liang)從(cong)0開(kai)始逐漸遞增,隨著數(shu)量(liang)達到(dao)minTablesPerVnode后(hou),開(kai)始創(chuang)建(jian)(jian)下(xia)一(yi)(yi)(yi)個(ge)(ge)vnode并繼續在其中(zhong)建(jian)(jian)表(biao)(biao)。之后(hou),重(zhong)復該過(guo)程(cheng)直到(dao)vnode數(shu)量(liang)達到(dao)maxVgroupsPerDb。之后(hou),TDengine將回到(dao)第一(yi)(yi)(yi)個(ge)(ge)vnode繼續創(chuang)建(jian)(jian)新表(biao)(biao),在補充每(mei)個(ge)(ge)vnode的(de)(de)表(biao)(biao)數(shu)達到(dao)tablelncStepPerVnode數(shu)量(liang)后(hou),后(hou)續以tablelncStepPerVnode為步長繼續在vnode中(zhong)依次創(chuang)建(jian)(jian)表(biao)(biao),直到(dao)建(jian)(jian)完全(quan)部表(biao)(biao)。(描述看著繁瑣,自己動手跑(pao)一(yi)(yi)(yi)遍會(hui)很直觀)
明(ming)白(bai)了(le)這個邏輯后(hou),我們可(ke)以再(zai)來回頭看為什么(me)會出(chu)現場景一的(de)情況。答案(an)已經很簡(jian)單(dan)了(le),因為minTablesPerVnode這個參數的(de)值默認是1000,所(suo)以前1000個表(biao)肯定(ding)會只出(chu)現在第一個vnode里,這就給用(yong)戶造成了(le)數據分配并(bing)不平均的(de)錯覺。
那么要(yao)如何調整成我們(men)預(yu)期的效果呢(ni)。
別急——在此之前我們還需要再多了解一下這個參數:maxVgroupsPerDb。大家可(ke)能在taos.cfg中留意過maxVgroupsPerDb這個參數的(de)(de)值(zhi)默認是(shi)0,根(gen)據參數描述,0代表的(de)(de)是(shi)自動配置(zhi)。但是(shi)關于這個自動配置(zhi)的(de)(de)詳情在官網上是(shi)有解釋(shi)的(de)(de):“每(mei)個 Database 可(ke)以(yi)創建固定數目的(de)(de) vgroup,默認與 CPU 核數相同(tong),可(ke)通過 maxVgroupsPerDb 配置(zhi)”。
如果不了解vgroup概念(nian),建議到官網查看:

?結合文章開頭說(shuo)過的(de)vnode概念——每個vnode都是(shi)具有獨(du)立的(de)運(yun)行線程的(de),這樣(yang)就(jiu)一目(mu)(mu)了(le)然(ran)了(le)——如(ru)此設計默認值的(de)原(yuan)因就(jiu)是(shi)希望(wang)vnode數等于cpu核數,從而充分地(di)利用CPU資源,達到最大化服務器性能的(de)目(mu)(mu)的(de)。
好(hao),現在(zai)我們終于可(ke)以回到(dao)場景一并提出我們的解(jie)決(jue)方(fang)案了。
假設我們是(shi)4核服務器,那么(me)默(mo)認(ren)的最大vgroups就(jiu)是(shi)為4個。進入場景一(yi)當中(zhong),每個vnode只要存(cun)儲300個表就(jiu)好(hao)了。這(zhe)時候只需要調(diao)整minTablesPerVnode值為300,這(zhe)樣(yang)就(jiu)可以做(zuo)到(dao)表均(jun)勻分(fen)布在數據節點中(zhong)了。
場(chang)景(jing)一屬于相對(dui)(dui)特(te)殊(shu)的情況,而默(mo)認(ren)配置卻只能針(zhen)對(dui)(dui)最通用的一個(ge)場(chang)景(jing)。對(dui)(dui)于大部(bu)分用戶來說(shuo),只要(yao)你的測試場(chang)景(jing)是(shi)創(chuang)建萬(wan)(wan)表級別,都(dou)是(shi)可(ke)以看到表在vnode中(zhong)按(an)序且(qie)平(ping)均分配的。比如你有一臺4核CPU的機器(qi),計劃創(chuang)建4萬(wan)(wan)個(ge)表。那么(me)使用默(mo)認(ren)配置就會生成4個(ge)vnode,最終(zhong)的結果就是(shi)每個(ge)vnode存儲(chu)1萬(wan)(wan)張表,就不會出現數(shu)據不均的現象了。
這里我(wo)們可(ke)以多(duo)討論一(yi)下,既然默認配置的(de)maxVgroupsPerDb是(shi)可(ke)以充分(fen)利用CPU的(de)話(hua)。那么(me)這個(ge)參數還有什么(me)修改(gai)價值呢(ni)?如果沒有修改(gai)價值的(de)話(hua)它為什么(me)還會(hui)是(shi)一(yi)個(ge)對外公開的(de)參數呢(ni)?
別急,我們接下來(lai)進入下一個場景(jing)。
假設你(ni)的(de)CPU核(he)數(shu)為4,但(dan)是我們把maxVgroupsPerDb設成8。其中只(zhi)有(you)前4個(ge)vnode的(de)數(shu)據(ju)會比(bi)較(jiao)熱,后續4個(ge)vnode中的(de)數(shu)據(ju)的(de)使(shi)用(yong)頻率則比(bi)較(jiao)低。看(kan)似多(duo)開了(le)(le)很多(duo)vnode,但(dan)是這樣的(de)設置和使(shi)用(yong)默(mo)認(ren)(ren)配置比(bi)起來(lai),反而會降低前四個(ge)vnode的(de)負擔從而增加(jia)性能。所以,默(mo)認(ren)(ren)參(can)數(shu)雖然通用(yong),但(dan)是有(you)時候適當的(de)修改會讓數(shu)據(ju)庫變(bian)(bian)得更(geng)好,這就需(xu)要使(shi)用(yong)者結合實(shi)際(ji)業(ye)務(wu)場景做(zuo)評(ping)估了(le)(le)。目(mu)前,該(gai)參(can)數(shu)仍(reng)是一個(ge)全局變(bian)(bian)量(liang),未來(lai)或許會變(bian)(bian)成數(shu)據(ju)庫級別(bie)的(de)變(bian)(bian)量(liang)以方便不同數(shu)據(ju)庫之間業(ye)務(wu)的(de)差異(yi)。
而minTablesPerVnode,tablelncStepPerVnode這兩個變(bian)量由于使用相(xiang)對復雜,所(suo)以(yi)目前并沒有出現在(zai)(zai)taos.cfg當中(zhong)(zhong)(zhong),屬于標題中(zhong)(zhong)(zhong)提到的(de)“神秘參(can)數(shu)(shu)”。雖(sui)然(ran)它們(men)設置了(le)適當的(de)默認值(1000)來應(ying)對大(da)多數(shu)(shu)場景,但(dan)是當業(ye)務(wu)場景發生變(bian)動出現不適配的(de)時候(hou),就需(xu)要我們(men)自己手(shou)動修改(gai)這些參(can)數(shu)(shu)了(le)。具體修改(gai)方(fang)式如(ru)下:打(da)開(kai)taos.cfg后在(zai)(zai)空白區域(yu)添加如(ru)下內容,重(zhong)啟數(shu)(shu)據庫(ku)服(fu)務(wu)進程即可。如(ru)果是集群環境,那么需(xu)要在(zai)(zai)每一(yi)個節點(dian)的(de)taos.cfg中(zhong)(zhong)(zhong)都做一(yi)樣的(de)配置后重(zhong)啟數(shu)(shu)據庫(ku)服(fu)務(wu)進程。


場景二:vnode分布不均勻
這種情況就比(bi)較(jiao)簡單了,在批量創(chuang)建完很(hen)多表后,有時候你(ni)可能(neng)會發現(xian):“咦?為什么這個數據節(jie)點上有6個vnode,另外一(yi)個節(jie)點只有2個vnode。”
在解釋這種情(qing)況(kuang)之(zhi)前,我們需要(yao)知道另一個(ge)TDengine相(xiang)當重要(yao)的(de)概念——mnode(管理(li)節點)。
關于mnode,官方(fang)文檔的描述(shu)十分清晰:
管(guan)理節(jie)(jie)點(mnode): 一個(ge)虛擬的(de)邏輯單(dan)元(yuan),負(fu)責所(suo)有數據節(jie)(jie)點運(yun)行狀(zhuang)態(tai)的(de)監控和維(wei)護,以及節(jie)(jie)點之間的(de)負(fu)載均衡。同時,管(guan)理節(jie)(jie)點也負(fu)責元(yuan)數據(包括用戶、數據庫(ku)、表、靜態(tai)標簽(qian)等)的(de)存儲和管(guan)理,因(yin)此也稱為 Meta Node。在集群(qun)中,為了保證mnode的(de)高可用,可以配置多個(ge)mnode副本(ben),副本(ben)數由系(xi)統配置參數numOfMnodes決定,有效范(fan)圍為1-3。
可以看出(chu),mnode和vnode一樣,都(dou)是以master-slave的(de)(de)(de)模式分布在節點中的(de)(de)(de)。因(yin)此,在做數據的(de)(de)(de)負(fu)載均衡的(de)(de)(de)時候,mnode也會是被計算在內的(de)(de)(de),而具體(ti)的(de)(de)(de)計算方式就是,一個(ge)mnode等價于n個(ge)vnode,這(zhe)個(ge)n就是由下(xia)面這(zhe)個(ge)參數控制的(de)(de)(de)。

而(er)查看mnode的(de)分配情況的(de)命令(ling)如(ru)下(xia):

這回我們(men)就知(zhi)道(dao)為什么會出現場景二的(de)(de)情況了——只有2個vnode分(fen)布(bu)的(de)(de)數據節(jie)點(dian)上一定是有mnode在工作的(de)(de)。
正是它,頂替了原本應該(gai)出現在這的vnode名額。
尾記
寫到這里就差不多了,但作為作者很想和大(da)家閑聊幾句(ju)。
TDengine雖然使用簡單方便,但是想要最大化它的價值還是需要一番研究的。而官方文檔是作為(wei)TDengine的(de)百科全書而存(cun)在(zai)的(de),某(mou)種程度上,它可能并不適合串聯實(shi)際應用(yong)場(chang)景。所以(yi),為(wei)了填補這塊空(kong)白,所以(yi)我們在(zai)推送的(de)文章(zhang)中會很注意產品(pin)與實(shi)際場(chang)景的(de)結合以(yi)及串聯。最終(zhong)的(de)目標,是讓我們的(de)文章(zhang)能夠形成在(zai)很多實(shi)際使(shi)用(yong)場(chang)景下(xia)的(de)閉環(huan)說明書。這樣(yang),就(jiu)可以(yi)讓TDengine用(yong)戶的(de)使(shi)用(yong)體驗大幅(fu)上升。
空口無憑,我們如何做到串聯不同實際的應用場景呢。很簡單,讀完本篇文章可能您已經了解了如何正確的配置集群的數據分布了。結合文章《TDengine 的用戶如何優化數據的寫入速度?》,想必您又已經對寫入數據的性能調試有了一定的認知。再讀文章《【社區精選】在Docker環境下,TDengine的客戶端為什么連不上集群?》,您又對在docker環(huan)境下搭(da)建TDengine集群搭(da)建有了(le)一(yi)定的了(le)解(jie)。
搭建(jian)TDengine的(de)知識體(ti)系,就和搭建(jian)TDengine的(de)集群(qun)一樣,需要一步一步慢慢積累起來。
開源文化(hua)的本質就是互相幫助,社區用(yong)戶(hu)為我們貢獻了很多(duo)。因此,我們也希望可(ke)以(yi)用(yong)同樣的方式回報大家。


























