2012-02-01 46 views
4

我正在研究一個項目,我們有一個原子陣列作爲哈希函數。每當用戶連接到服務器時,都會散列某個值,並將該散列用作索引來查找數組中的元素,然後返回該元素。 「外力」(由長期運行的gen_server處理)能夠改變這個數組,所以我不能簡單地對它進行硬編碼。我的問題是如何「託管」這個數組。Erlang:在陣列上分佈式工作

我的第一個實現是一個簡單的gen_server,它保存了數組的副本並將其發送給需要它的任何人。詢問它的過程可以遍歷它並獲得他們想要的索引。這個實現有過多的內存使用,我認爲這是因爲這個數組的副本太多了。

我目前的實現有一箇中央gen_server處理這個數組的狀態,以及處理實際請求的子節點。當狀態改變時,中央gen_server更新孩子。當一個進程想要找到它的散列結果時,它會將其索引號發送給中央gen_server,中央gen_server將該請求轉發給其中一個子進程。子代遍歷其「本地」列表,並將生成的原子發送回原始進程。

當前實施方案的問題在於它在高流量下陷入困境。我嘗試過使用越來越多的孩子,但我很確定中央gen_server是瓶頸。

有沒有人有更好的解決我的問題的任何想法?

編輯:%s /陣列/列表/ g的

回答

6

我建議您使用ETS Tables。我認爲Array方法效率不夠高。通過在應用程序後端中公開創建的ETS Table,任何進程都可以在需要時立即查找項目。在當前較新版本的erlang中有ETS Tables有併發訪問的能力。

%% Lets create a record structure 
%% where by the key will be a value 
%% in the array. 
%% For now, i do not know what to 
%% put in the field: 'other'
-record(element,{key,other}).
create_table(TableName)-> Options = [ named_table,set, public, {keypos,2}, %% coz we are using record NOT tuple {write_concurrency,true} ], case ets:new(TableName,Options) of TableName -> {success,true}; Error -> {error,Error} end.
lookup_by_hash(TableName,HashValue)-> try ets:lookup(TableName,HashValue) of Value -> {value,Value}; catch X:Y -> {error,{X,Y}} end.
使用這種安排,您將避免產生來自單個gen_server持有數據的 A Single Point of Failure。這些數據是許多流程所需要的,因此不應該由一個流程來保存。這是任何時候只要需要查看就可以通過任何進程訪問的表格。

數組中的值應該轉換爲格式爲 element的記錄,然後插入 ETS Tables。這種方法的

優點

1.我們可以創建許多 ETS Tables儘可能
2.一種ETS表可以處理許多比數據結構以上的元素,例如列表或具有低得多的可比存儲器消耗的數組。
3. ETS Tables可以同時訪問的任何進程範圍內,因此你將不需要一箇中央進程或服務器來處理數據
4.一個進程或gen_server持有這些數據,意味着如果其妥協(由於一個完整的郵箱),它將不可用,因此需要該陣列的進程將不得不等待這一臺服務器重啓或者我不知道......
5.通過發送請求消息和製作來訪問陣列數據相同數組的副本到每個需要它的進程不是「Erlangic」設計。
6。最後, ETS Tables所有權可以從流程轉移到流程。當擁有的進程崩潰時(只有gen_servers可以檢測到它們正在死亡[注意這一點]),它可以將 ETS Table轉移到另一個進程接管。點擊這裏: ETS Give Away

這就是我的想法。

1

不知道這是否會有所幫助,但你可以管理(從哈希業務獨立)在分佈式哈希表中央的哈希值,就像任何其他值?這樣多個進程可以承擔負載而不是一箇中央進程。

從我讀到的數組看來並不需要是一個數組。