2011-03-31 121 views
7

我對我的BC論文項目的工作應該是寫在Scala和阿卡一的Minecraft服務器之間的狀態。服務器應該易於部署在雲中或集羣上(不知道我是否使用了適當的術語......它應該在多個節點上運行)。然而,我是阿卡的新手,我一直在想如何實現這樣的事情。我現在想弄清楚的問題是如何在不同節點上的演員之間共享狀態。我的第一個想法是有一個駱駝演員會從我的世界客戶端讀取TCP流,然後將其發送到負載平衡器這將選擇將處理請求,然後發送通過TCP給客戶一些響應的節點。比方說,我有一個AuthenticationService實現actor來檢查用戶提供的憑據是否有效。每個節點都有這樣的角色(或者更多角色),並且所有角色應始終具有完全相同的數據庫(或狀態)的用戶。我的問題是,保持這種狀態的最佳方法是什麼?我已經想出了一些解決方案,我能想到的,但我沒有做這樣的事,所以請指出故障:阿卡和演員在集羣

解決方案#1:保持狀態在數據庫中。這可能對於這種身份驗證示例非常有效,其中狀態僅由用戶名和密碼列表表示,但在狀態包含不能輕易分解爲整數和字符串的對象的情況下可能不起作用。解決方案#2:每次向某個演員發出會改變其狀態的請求時,演員將在處理請求之後向所有其他將改變的相同類型的演員廣播關於該改變的信息他們的狀態根據原演員發送的信息。這看起來效率很低,而且很笨拙。

溶液#3:具有特定節點作爲排序的狀態下的節點,其中存在將是代表整個服務器的狀態的演員。任何其他演員,除了此類節點中的演員都沒有狀態,並且每次需要某些數據時都會詢問「狀態節點」中的演員。這似乎也是低效率的,並且有點過錯 - 不安全。

所以你有它。只有我真正喜歡的解決方案是第一個,但正如我所說的,它可能只適用於非常有限的問題子集(當狀態可以分解爲redis結構時)。來自更有經驗的大師的任何迴應都會非常受歡迎。 的問候,托馬斯·赫爾曼

回答

3

解決方案#1可能可能會很慢。此外,這是一個瓶頸和單點故障(意味着如果節點與數據庫失敗,應用程序停止工作)。解決方案#3也有類似的問題。

解決方案#2比它顯得不那麼微不足道。首先,這是一個單一的失敗點。第二,有沒有對原子或其他排序保證(如規則)讀取或寫入,除非你做一個total order broadcast(這比常規的廣播更貴)。實際上,大多數分佈式寄存器算法都會在內部進行廣播,所以雖然效率低下,但可能是必要的。

從你所描述的東西,你需要爲你分配寄存器原子。原子性是什麼意思?原子性意味着以併發讀寫的順序進行的任何讀取或寫入看起來就像在單個時間點發生一樣。 非正式,在溶液#2具有單個演員保持寄存器,這保證如果2個後續寫入W1,然後W2到寄存器發生(意味着2個廣播),則沒有其他演員從寄存器讀取的值將按照與第一個W1和第二個W2不同的順序讀取它們(實際上它比這更多地涉及)。如果您通過後續廣播的幾個示例(消息在不同時間點到達目的地),您會發現這樣的排序屬性根本無法保證。

如果排序保證或原子性不是問題,某種基於八卦的算法可能會緩慢地將更改傳播到所有節點。這可能不會對你的例子很有幫助。

如果你想完全容錯和原子,我建議你對拉希德Guerraoui和路易斯·羅德里格斯,或與分佈式寄存器抽象的部件可靠的分佈式編程閱讀本book。這些算法建立在消息傳遞通信層之上,並維護支持讀寫操作的分佈式寄存器。您可以使用這種算法來存儲分佈式狀態信息。然而,它們不適用於數以千計的節點或大型集羣,因爲它們不能縮放,通常在節點數量上具有複雜性多項式。另一方面,您可能不需要跨所有節點複製分佈式寄存器的狀態 - 將其複製到節點的子集(而不是僅一個節點)並訪問這些節點以讀取或寫入從中提供一定的容錯水平(只有當整個節點子集失敗時,寄存器信息纔會丟失)。你可以調整書中的算法來達到這個目的。

+0

嘿,非常感謝你的回答。這似乎比我想象的要難得多:]。我實際上不得不考慮這個問題一段時間,以確定我是否真的需要操作的原子性。我會檢查出這本書,謝謝你的提示。或者也許我可以使用其他節點作爲主節點的從節點,它可以容納所有的信息,而其他節點只需接收消息並對從主節點接收到的數據進行一些計算。儘管如此,仍然感覺不對。 – Arg 2011-03-31 18:28:04

+0

不客氣。請記住,擁有主節點的問題始終是單點故障。如果您擔心容錯,那可能是一個問題。也許你也可以查看一些分佈式散列表實現來查看它們是否可以幫助你(例如Apache Cassandra)。 – axel22 2011-03-31 18:39:30

+0

是的,容錯並不是什麼大問題。無論如何,目前還不是。此外,無論如何,我需要某種特權節點。 Minecraft客戶端將連接到的一個。 – Arg 2011-03-31 18:42:48