六月婷婷AV,国产偷窥猎奇福利二区,日韩三级片。,好吊色网站,日韩成人中文在线视频,国产亚洲午夜啪啪,亚洲欧美另类国产精品,国产成人av1,任你艹在线观看

TDengine 資深研發(fā)分享解決思路,長查詢不再成為系統(tǒng)性能瓶頸!

長查詢問題指的是在數(shù)據(jù)庫寫入和查詢并存的日常應(yīng)用場景中,存在處理數(shù)據(jù)量大且耗時很長的查詢長時間占用系統(tǒng)資源,導(dǎo)致寫入可能被阻塞的問題。有時,查詢代碼對于資源釋放函數(shù)調(diào)用的遺忘也可能以長查詢問題的形式表現(xiàn)出來。如何在數(shù)據(jù)寫入不被阻塞同時,保證長查詢的正確進(jìn)行是一個具有挑戰(zhàn)性的問題。

盡管在絕大多數(shù)時序數(shù)據(jù)使用場景下,用戶不太可能遇到這個問題,但一旦出現(xiàn),也會讓人頭疼不已。為了解決這一問題,TDengine 研發(fā)團(tuán)隊(duì)一直致力于不斷優(yōu)化系統(tǒng),提高查詢性能和響應(yīng)速度。本文將深入剖析這一挑戰(zhàn),并探討如何應(yīng)對和解決長查詢問題,以提升 TDengine 在復(fù)雜查詢場景下的表現(xiàn)。

在分析長查詢問題之前,我們首先需要為大家普及一下 TDengine 的寫入/查詢并發(fā)機(jī)制。

數(shù)據(jù)寫入/讀取機(jī)制

Vnode 是 TDengine 中存儲和查詢數(shù)據(jù)的基本單元,這里主要介紹 Vnode 的寫入/讀取及并發(fā)機(jī)制。

數(shù)據(jù)寫入機(jī)制

TDengine 資深研發(fā)分享解決思路,長查詢不再成為系統(tǒng)性能瓶頸! - TDengine Database 時序數(shù)據(jù)庫

  • 每個 Vnode 在創(chuàng)建時都會根據(jù) DB 參數(shù)分配一定數(shù)量的內(nèi)存
  • 這些內(nèi)存在 Vnode 中被分為三個內(nèi)存塊
  • 每個 Vnode 只有一個線程寫入
  • Vnode 在寫入時,會從內(nèi)存塊的空閑列表 (free list) 中分配一個內(nèi)存塊(mem),供數(shù)據(jù)寫入使用
  • 當(dāng)內(nèi)存塊中數(shù)據(jù)寫入超過一定量后,開始落盤(imem),同時分配一個新的內(nèi)存塊供數(shù)據(jù)寫入使用
  • 當(dāng)內(nèi)存塊全部用完,沒有空閑內(nèi)存塊時,寫入會被阻塞,一直等待有內(nèi)存塊釋放出來

數(shù)據(jù)查詢機(jī)制

  • 查詢分多批次進(jìn)行,每次返回部分?jǐn)?shù)據(jù),然后該查詢等待下一次拉取數(shù)據(jù)的請求
  • 查詢結(jié)果是內(nèi)存(mem/imem)數(shù)據(jù)和硬盤數(shù)據(jù)合并的結(jié)果
  • 查詢開始時,會先 take snapshot,引用(ref) mem/imem 以及硬盤文件
  • 查詢結(jié)束時,unref mem/imem,如果內(nèi)存塊的引用計(jì)數(shù)變?yōu)?0,則內(nèi)存塊被回收到空閑鏈表中
TDengine 資深研發(fā)分享解決思路,長查詢不再成為系統(tǒng)性能瓶頸! - TDengine Database 時序數(shù)據(jù)庫

長查詢問題

時序數(shù)據(jù)絕大部分查詢持續(xù)時間都比較短,如查詢表/超級表的最后一條記錄、做 count 或 sum 類的聚合查詢等。這類查詢持續(xù)時間較短,對于 mem/imem 的占用時間也較短,查詢很快會釋放 MemTable 供 Vnode 回收再次利用,從而不影響寫入的進(jìn)行。但是,如果存在一個持續(xù)時間很長的查詢,如超過 1 小時或 1 天的查詢,這時候就會出現(xiàn)此類問題。當(dāng)然,只有一個長查詢的情況下,問題也不大,因?yàn)?Vnode 的內(nèi)存池默認(rèn)被分成了 3 個內(nèi)存塊,一個長查詢最多占用兩個內(nèi)存塊,還剩余一個內(nèi)存塊可以用來進(jìn)行持續(xù)寫入。但是如果存在多個長查詢,Vnode 中的所有內(nèi)存塊都可能被長時間占用,無法進(jìn)行回收,從而導(dǎo)致寫入停止的情況。

另外,如果查詢部分的代碼存在 BUG,忘記關(guān)閉查詢句柄,也會導(dǎo)致 mem/imem 被長期占用,阻塞寫入。這個問題在 TDengine 訂閱和流計(jì)算功能中曾經(jīng)就出現(xiàn)過。

TDengine 資深研發(fā)分享解決思路,長查詢不再成為系統(tǒng)性能瓶頸! - TDengine Database 時序數(shù)據(jù)庫

長查詢問題解決方案

我們需要一個方案,可以在長查詢大量存在、或用戶應(yīng)用代碼有問題沒有及時關(guān)閉查詢句柄、甚至產(chǎn)品代碼有問題的情況下,也能達(dá)到既不阻塞寫入且不讓長查詢失敗。該方案如下:

  1. 查詢在獲取數(shù)據(jù)快照時,將查詢句柄注冊到它所占用的內(nèi)存塊上,同時注冊一個 reseek 函數(shù)
  2. 當(dāng)查詢結(jié)束關(guān)閉句柄時,該查詢將句柄從它所占用的所有內(nèi)存塊上注銷
  3. 當(dāng)寫入發(fā)現(xiàn)沒有可用內(nèi)存塊時,嘗試回收已經(jīng) COMMIT 但是仍舊被查詢占用的最老的內(nèi)存塊
  4. 寫入線程回收內(nèi)存塊時,遍歷所有注冊在該內(nèi)存塊上的注冊句柄,調(diào)用 reseek 函數(shù)
  5. reseek 函數(shù)會嘗試鎖查詢句柄,如果鎖句柄成功,則將查詢句柄設(shè)置為 RESEEK 狀態(tài),同時將查詢的狀態(tài)保存下來并 untake snapshot,歸還占用的所有內(nèi)存塊
  6. 查詢線程在查詢活躍周期開始時鎖查詢句柄,然后檢查是否為 RESEEK 狀態(tài),如果為 RESEEK 狀態(tài),重新 take snapshot,并根據(jù)保存的查詢狀態(tài),恢復(fù)各種查詢變量,接著進(jìn)行查詢

從上述方案中我們可以看到:

  1. 寫入在發(fā)現(xiàn)內(nèi)存不足的條件下,可以主動回收非激活狀態(tài)的查詢占用的內(nèi)存塊,從而不會長時間阻塞寫入
  2. 長查詢在寫入回收其所占用的內(nèi)存塊后,可以根據(jù)自己保存的查詢狀態(tài),重新 take snapshot,繼續(xù)查詢,從而不會讓長查詢失敗
TDengine 資深研發(fā)分享解決思路,長查詢不再成為系統(tǒng)性能瓶頸! - TDengine Database 時序數(shù)據(jù)庫

TDengine 資深研發(fā)分享解決思路,長查詢不再成為系統(tǒng)性能瓶頸! - TDengine Database 時序數(shù)據(jù)庫

答疑解惑

Q:如何解決死鎖問題?

A:在寫入回收內(nèi)存塊時,需要遍歷查詢句柄注冊鏈表,因此需要對鏈表進(jìn)行加鎖操作,即需要鎖定鏈表的鎖。在調(diào)用 reseek 回調(diào)時,也需要鎖定查詢句柄的鎖。這樣就存在寫入線程出現(xiàn) lock(mutex_list)–>lock(mutex_qhandle) 的情況。而在查詢結(jié)束時,需要將句柄從注冊鏈表中移除,導(dǎo)致出現(xiàn) lock(mutex_qhandle)–>lock(mutex_list) 的情況。如果兩個線程不按照相同的順序?qū)蓚€鎖進(jìn)行加鎖,就會產(chǎn)生死鎖的問題。

為了解決這個問題,可以采用以下優(yōu)化方案:

  1. 使用 trylock 替代 lock:對于寫入回收調(diào)用 reseek 函數(shù)的場景,可以嘗試使用 trylock 而不是直接使用 lock 來獲取查詢句柄的控制權(quán)。通過 trylock 嘗試獲取鎖,可以避免線程因等待鎖而被阻塞,從而減少死鎖的風(fēng)險。
  2. 多次嘗試機(jī)制:在使用 trylock 的基礎(chǔ)上,可以結(jié)合多次嘗試的機(jī)制。如果一次 trylock 未成功獲取鎖,可以進(jìn)行多次嘗試,直至成功獲取鎖或達(dá)到嘗試次數(shù)上限為止。這樣能夠增加獲取鎖的機(jī)會,降低死鎖風(fēng)險。
Q:長查詢會不會一直被寫入 reseek,從而導(dǎo)致查詢一直恢復(fù)?

A:不會存在這種情況。查詢在每次打開句柄時,會給一個版本號,這個版本號是已經(jīng)寫入 Vnode 中的最新數(shù)據(jù)的版本號,查詢只能看到版本號小于等于該版本號的數(shù)據(jù)。當(dāng) take snapshot 時,會根據(jù) mem/imem 中的數(shù)據(jù)是否被查詢版本號覆蓋而決定 mem/imem 是否被該查詢引用。隨著數(shù)據(jù)的寫入,新的 mem/imem 中的數(shù)據(jù)肯定都大于該查詢創(chuàng)建時給的版本號,因此,新的 mem/imem 不會被長查詢引用。這樣一來,一個長查詢最多會被寫入 RESEEK 兩次。

TDengine 資深研發(fā)分享解決思路,長查詢不再成為系統(tǒng)性能瓶頸! - TDengine Database 時序數(shù)據(jù)庫

以上就是 TDengine 資深研發(fā)人員對解決長查詢問題進(jìn)行的深入探討。如果你還有關(guān)于查詢的更多問題想要討論或交流,歡迎添加小T vx:tdengine 尋求幫助,也可以在下方留言區(qū)進(jìn)行相關(guān)評論,靜待回復(fù)即可~