2012-02-01 53 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

不知道这是否会有所帮助,但你可以管理(从哈希业务独立)在分布式哈希表中央的哈希值,就像任何其他值?这样多个进程可以承担负载而不是一个中央进程。

从我读到的数组看来并不需要是一个数组。