2011-04-28 60 views
3

我有一個收集會話數據的系統。會話由許多不同的事件組成,例如「會話開始」和「執行的操作X」。沒有辦法確定會話何時結束,所以相反,心跳事件會定期發送。你如何對分佈式系統中沒有事件做出反應?

這是主要的併發症:沒有確定的方式,如果一個會話已經結束,唯一的辦法就是儘量不存在的事件,即沒有更多的心跳反應。我如何在分佈式系統中有效且正確地完成這項工作?

下面是一些背景的問題:

事件必須被組裝成表示會話中的對象。會話對象稍後會使用來自其他系統的附加數據進行更新,並最終用於計算會話數量,平均會話長度等。

系統必須水平縮放,因此有多個服務器可以接收事件以及處理它們的多個服務器。屬於同一會話的事件可以發送到不同的服務器並由其處理。這意味着我們無法保證它們將按順序處理,並且還有其他複雜情況,意味着事件可能會重複(並且總會有一些丟失的風險,無論是在它們到達我們的服務器之前,還是在處理完成之前)。

大部分情況已經存在,但我沒有很好的解決方案來有效地和正確地確定會話何時結束。我現在的做法是定期搜索「不完整」會話對象的集合,查找任何未等待兩次心跳的時間的更新,然後將這些對象移至另一個具有「完成」會話的集合。此操作既耗時又低效,並且水平伸縮效果不佳。基本上,它包括對代表最後一個時間戳的列進行排序,並過濾掉任何不夠長的行。聽起來很簡單,但很難並行化,如果你經常這樣做,你就不會做其他任何事情,數據庫會忙於過濾數據,如果你不經常做足夠的話,每次運行都會很慢,因爲有處理太多。

我想反應過來的時候會話尚未一會兒更新,不輪詢每個會話,看它是否也已更新。

更新:只是爲了給你的感覺;在任何時候都有數十萬個會話活動,最終會有數百萬個會話。浮現在腦海

+0

多久你需要知道,如果一個會話已經完成? – 2011-04-28 12:28:26

+0

大約在幾分鐘內。 – Theo 2011-04-28 18:23:50

回答

2

一種可能性:

在你的數據庫表中記錄了最近一次會議是跟蹤會話,添加時間戳字段(如果你沒有的話),「活躍」 。每當你有心跳時更新時間戳。

當你創建一個會話,安排「計時器事件」後,一些適當的延時消防檢查會話是否過期。當計時器事件觸發時,請檢查會話的時間戳,以查看在計時器等待的時間間隔內是否有更多的活動。如果是這樣,會話仍處於活動狀態,因此安排另一個計時器事件以便稍後再次檢查。如果沒有,會話超時,所以刪除它。

如果你使用這種方法,每一屆總會有負責檢查是否它是過期的,但不同的服務器可以負責不同的會話,所以工作量可以左右均勻地分佈在一臺服務器。當心跳進入時,哪個服務器處理它並不重要,因爲它只是更新數據庫中的一個時間戳(大概)在所有服務器之間共享。

由於您將獲得定期計時器事件,使您可以檢查會話是否已過期,即使尚未過期也仍然存在一些輪詢。如果每次檢測信號到達時您可以取消掛起的定時器事件,但可以避免使用多個棘手的服務器:處理心跳的服務器可能與預定定時器的服務器不同。無論如何,所涉及的數據庫查詢是輕量級的:只需通過主鍵查找一行(會話記錄),而無需進行排序或不等式比較。

+0

在理論上使用計時器可以工作,但我不確定如何在實踐中做到這一點。當會話更新時,如何確保定時器延遲(即取消並設置爲新時間)?如果你沒有把握好,你最終會被虛假檢查所淹沒。在任何時候都有數十萬(並最終有望達到數百萬)會話。 – Theo 2011-04-28 07:20:34

0

所以你正在收集心跳;我想知道是否可以有一個批處理過程(或者其他東西)在收集的心跳中尋找表示會話結束的模式。

準確度的高低取決於心跳的頻率和收集心跳的頻率。

好處是你正在通過一個機制處理所有的心跳(在一個地方 - 你不必輪詢每個心跳),所以應該能夠擴展 - 如果它是一個以數據庫爲中心的解決方案那應該能夠處理大量的數據,對吧?

有可能是一個更優雅的解決方案,但我的腦子有點滿剛纔:)

+0

我知道心跳之間的時間間隔,因此找出一個會話已經結束是沒有問題的(雖然不完美,但是兩個錯過的心跳足以說明會話已結束)。但這就是我在我的問題中描述的(尋找「我現在​​這樣做的方式」,它位於最後一段的第三段)。問題是這種機制成爲瓶頸。 – Theo 2011-04-29 11:12:56