簡體   English   中英

您如何應對分布式系統中沒有事件的情況?

[英]How do you react to the absence of an event in a distributed system?

我有一個收集 session 數據的系統。 session 由許多不同的事件組成,例如“會話開始”和“動作 X 執行”。 無法確定 session 何時結束,因此會定期發送心跳事件。

這是主要的並發症:無法確定 session 是否已結束,唯一的方法是嘗試對沒有事件做出反應,即不再有心跳。 如何在分布式系統中有效且正確地做到這一點?

這是問題的更多背景:

然后必須將事件組合成代表會話的對象。 session 對象稍后會使用來自其他系統的附加數據進行更新,最終它們用於計算會話數、平均 session 長度等。

系統必須水平擴展,因此有多個服務器接收事件,並有多個服務器處理它們。 屬於同一 session 的事件可以發送到不同的服務器並由不同的服務器處理。 這意味着無法保證它們會按順序處理,並且還有其他復雜性意味着事件可以重復(並且總是存在丟失某些事件的風險,無論是在它們到達我們的服務器之前,還是在處理時)。

其中大部分已經存在,但是對於如何有效和正確地確定 session 何時結束,我沒有很好的解決方案。 我現在這樣做的方式是定期搜索“不完整” session 對象的集合,以查找在等於兩個心跳的時間內未更新的任何對象,然后將它們移動到具有“完整”會話的另一個集合中。 此操作耗時且效率低下,並且無法很好地橫向擴展。 基本上,它包括在代表最后時間戳的列上對表進行排序,並過濾掉任何不夠舊的行。 聽起來很簡單,但是很難並行化,如果你經常這樣做,你將不會做任何其他事情,數據庫將忙於過濾你的數據,如果你不經常這樣做,每次運行都會很慢,因為有太多無法處理。

當 session 有一段時間沒有更新時,我想做出反應,不要輪詢每個 session 以查看它是否已更新。

更新:只是為了給你一種規模感; 任何時候都有數十萬個會話處於活動狀態,最終將有數百萬個。

想到的一種可能性:

在跟蹤會話的數據庫表中,添加一個時間戳字段(如果您還沒有),該字段記錄 session 上次“活動”的時間。 每當您收到心跳時更新時間戳。

當您創建 session 時,安排一個“計時器事件”在適當的延遲后觸發,以檢查 session 是否應該過期。 當計時器事件觸發時,檢查會話的時間戳以查看在計時器等待的時間間隔內是否有更多活動。 如果是這樣,則 session 仍處於活動狀態,因此請安排另一個計時器事件稍后再檢查。 如果不是,則 session 已超時,因此請將其刪除。

如果使用這種方法,每個 session 將始終有一個服務器負責檢查它是否過期,但不同的服務器可以負責不同的會話,因此工作量可以均勻分布。 當心跳進入時,哪個服務器處理它並不重要,因為它只是更新(可能)在所有服務器之間共享的數據庫中的時間戳。

仍然涉及一些輪詢,因為您將獲得定期計時器事件,這些事件使您檢查 session 是否已過期,即使它尚未過期。 如果您可以在每次心跳到達時取消掛起的計時器事件,則可以避免這種情況,但是對於多個服務器,這很棘手:處理心跳的服務器可能與安排計時器的服務器不同。 無論如何,所涉及的數據庫查詢是輕量級的:只需通過其主鍵查找一行(session 記錄),沒有排序或不等式比較。

所以你正在收集心跳; 我想知道您是否可以有一個批處理(或其他東西)來遍歷收集的心跳,以尋找暗示 session 結束的模式。

准確度取決於心跳的規律性以及您掃描收集到的心跳的頻率。

優點是您通過單一機制處理所有心跳(在一個地方 - 您不必自己輪詢每個心跳)因此應該能夠擴展 - 如果它是一個以數據庫為中心的解決方案應該能夠處理大量數據,對吧?

可能有一個更優雅的解決方案,但我的大腦剛剛有點充實:)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM