2013-10-25 51 views
0

我們在許多單獨的線程/節點之間的會話中共享數據時遇到了問題。跨多個線程/節點的會話管理

場景如下所示: 存在一些類型爲String的全局池,例如123ABC-1299AA。 用戶嚮應用程序發送命令時需要取這個值中的一個。不能有兩個會話使用相同的值連接。

在環境中,我們有4個服務器,有50個線程在等待請求。

當前狀態: 我們存儲在Oracle數據庫映射值 - 會話中。使用UNIQUE值限制。當我們收到請求時,我們查詢表中的所有值,然後迭代池並忽略使用的值,找到一個空閒的值。如果另一個線程在迭代過程中提供了新的值,我們將獲得唯一約束,然後嘗試另一個線程。另外DataBase是爲一些持久性數據設計的,這個映射之王並不是持久性數據。

問題: Oracle不處理大量讀/寫操作的小表。行鎖爭用,重做日誌問題等。除了在數據庫中進行一些維護時,我們正在觀察超時,因爲db的性能正在下降。

要求:

會話
  • 價值之一,沒有重複。
  • 響應時間短,100ms以下。
  • 所有應用程序節點上的數據一致性。
  • 在某種失敗期間沒有丟失映射。
  • 解決方案應處理高達100 TPS的流量。

你建議在這種情況下使用什麼?

目前我們正在評估CouchBase的會話管理,但它有很多的錯誤,並且很差的故障切換(可能需要10分鐘)。

+0

我不能憑經驗說話,但我在Riak上看到的一些演示文稿,它非常穩定,表現很高:http://docs.basho.com/riak/1.4.0/cookbooks/use-cases/ session-storage/ –

+0

Couchbase用於這種用例很多。你能給我更多關於你看到的錯誤和故障結束的信息嗎? (故障轉移是立即的,根據您的配置可能需要一些時間,是系統發現一個節點下降的事實) –

+0

我們CouchBase的問題是,當一個節點出現故障時,無法保證數據在切換後保持一致。目前我們有兩個集羣,每個集羣有兩個節點。在羣集中切換很快,但在羣集之間切換可能需要幾分鐘的時間。並且還丟失數據。關於我們寫給Couchbase的錯誤,他們修復了這些錯誤。或者,如果這很重要,我們會自行修復並將補丁發送給CB。主要我們可以在java-client中看到錯誤。 – voncuver

回答

1

我認爲你不只是需要一個很好的數據庫選擇,但也有一些應用程序重組。我假設你正在使用一個集中的Oracle數據庫,並且你的每臺服務器都寫入同一個數據庫。而且我還假設您正在執行客戶端負載平衡,即您的客戶端隨機選擇其中一個應用程序服務器來發送請求。

因此,這裏有我的一些想法這一點:

- 你爲什麼不進行分片數據庫爲n個碎片(N你的情況= 4)。每當新的請求出現時,每個應用服務器都會查看自己的分片。想法是你想避免任何形式的爭奪。這裏有最壞的情況。如果最終出現所有請求都要到達應用程序服務器之一併且該應用程序服務器的碎片已滿,而其他插槽的碎片中有空插槽的情況。如果你的客戶隨機選擇一個應用服務器,你會沒事的。但是你仍然想要照顧最糟糕的情況。所以我的解決方案是:如果一個應用服務器意識到它的分片已滿,它將隨機選擇另一個應用服務器的分片,並將查詢該分片爲空插槽。所以請注意,您最終會遇到兩臺應用程序服務器可能正在讀取/寫入相同表格行的情況。但是發生這種情況的可能性會降低幾個數量級,並且您的架構更加穩定。

但是我們可以做更多的事情來處理2個應用程序服務器可能正在讀取/寫入同一個碎片的情況,因爲應用程序服務器的碎片已滿。這裏有一些想法: - Check-Then-Act在任何一種狀態共享系統中都是一個問題。因此,如果兩個應用程序服務器正在查看同一個空插槽的碎片,它們將競爭(爭用條件)。在這種情況下,我會做的是以這樣的方式編寫我的查詢,如果當前值與我讀取的值不同,那麼我的應用服務器邏輯將再次執行搜索。如果當前值與我讀取的值相同,則將該插槽標記爲非空。請注意,您需要將其作爲同一事務來做到原子級。它需要像比較和交換(CAS)。無論您使用SQL或NoSQL的數據庫如何,您都必須在應用程序中編寫邏輯以處理Check-Then-Act場景,以防出現競爭情況。

我也認爲Oracle不是一個好選擇。首先它的價格昂貴,其次它看起來像你所需要的是鍵值存儲,所以在我看來,oracle對我來說是一種矯枉過正。另外,如果你有一個Oracle數據庫,那麼你就有一個單點故障。

因此,整體而言,集羣(或分區)鍵值存儲是一種很好的方法。在我看來,Couchbase不是一個不錯的選擇。我用它來進行大規模會話管理。在我們的例子中,我們使用了Moxi來進行映射(爲了我們的couchbase節點)。在我們的例子中,如果couchbase節點停止運行,Moxi需要花費一些時間(大約2-5分鐘)才能意識到節點已經斷開並選擇了一個新的主節點複製副本。但是,如果您的應用程序更加敏感,則可以在不使用Moxi的情況下使用Couchbase羣集,並將映射請求的邏輯保存到應用程序的couchbase節點中。

但是在您當前的情況下,如果Oracle數據庫出現故障會發生什麼情況?我相信你的停機時間超過3-5分鐘。我們的故障轉移時間也是2-5分鐘,因爲我們有90多個couchbase節點。在你的情況下,你可能只需要幾個(4-5),故障轉移將在幾秒鐘內完成。

我會在你的情況下做的另一件事是,我希望應用程序提前預留一些插槽,以便我的讀寫速度變快。所以當一個應用程序保留了插槽時,這些節點將被標記爲「保留」。如果該應用程序服務器關閉,則其所有保留的節點都將被釋放。或者你可以寫這樣的查詢

如果session ==「reserved」和app_server.health!=「ACTIVE」,那麼節點被認爲是空閒的。

因此,通過僅僅在數據庫中寫入app_server.health = INACTIVE,您可以自動釋放由它標記的所有節點。我希望我傳達了這個想法

數據基礎架構縮放是一個有趣的問題,我喜歡的東西。如果您有任何問題,請告訴我,我很樂意提供幫助。

我的主要建議是:

- 在您使用GUID爲每個用戶會話,而不是預先計算會話ID(或價值)分配給每個用戶的你能不能採取的做法?

- 考慮分片。分片並不意味着採用集羣方法。您可以在單個節點中分割以避免數據庫表之間的爭用。

- 評估您的使用NOSQL。 Couchbase(文檔存儲)是很好的選擇,我用它來存儲大規模的用戶會話。如果你想要免費的開源替代品,Riak,Redis也不錯。 Redis不會拿出內置的集羣。但最有可能你不需要它。 Redis的超級通電功能將會非常快速的讀取和寫入。Twitter使用Redis保留所有用戶的推文。

- 最終你必須在你的代碼中處理競爭條件。因此,請避免競爭條件,但要準備好在發生這些情況時予以處理。

- 如果您只有一個Oracle數據庫,則您已經有單點故障,故障切換時間無論如何都是多分鐘(或幾小時)。因此,不要害怕冒險進入Couchbase,Voldemort等集羣鍵值庫。對於4-5筆記羣集,您的故障轉移將非常快速(以秒爲單位)

0

實際上,它是由3個節點組成的羣集,並具有故障轉移到第二集羣。 Oracle是首選,因爲它的可靠性和數據一致性。

在數據庫之間共享數據是選項,但是由於某種原因某個實例關閉時會出現問題。其他人將首先使用他們的部件,然後他們將嘗試使用第四部分。這是個問題,因爲這個實例每次都要檢查它的資源。所以獲得價值會慢得多。我們的目標是在不到0.5秒的時間內獲得價值。我們獲得了故障轉移,因此當一個節點發生故障時,沒有問題,因爲交換機需要幾秒鐘的時間。問題是實例掛起(節點進行查詢而不處理),或者當數據庫互連速度較慢時,一個節點鎖定某些行,另一個節點也嘗試鎖定(原始鎖定爭用)。

關於問題: - 我們需要爲會話分配唯一​​的值;所有這些價值的維護將很難在代碼,但它可能

- 我們的治理過程中不會同意這麼做,安全性,故障轉移等

- 我評估CouchBase,現在,它現在看起來不錯,但是我們遇到了故障轉移的問題,切換到另一個節點可能需要幾分鐘時間,而且也不能保證失敗節點將數據刷新到第二個節點。我會閱讀其他的。

- 通過Oracle,我們對另一個集羣/節點的故障切換對我們來說是透明的。最糟糕的情況是節點掛起時,通常是因爲一些oracle錯誤。那麼當50-80%的流量失敗時,我們有10分鐘的時間。

感謝您的回覆,我會深入評估CB並閱讀其他解決方案。