我不确定我是否遇到了问题,但我想这是一个可能的解决方案:
| Distribution:
parent | buffer = [hash(key, id)), data[id]]; send(buffer);
nodes | recv(buffer); h_id, data = buffer;
父节点使用一些本地key 为其发送的数据的id 部分生成一个散列值(h_id),本地节点将接收结果h_id 和数据本身.
| Reduction:
nodes | buffer = [h_id, data]; send(buffer);
parent | recv(buffer); h_id, data_id = buffer;
在逆流上,节点必须同时发送原始h_id和之前收到的数据,否则后面的验证会失败:
hash(key, data) == h_id
由于key 仅在父节点中已知,本地节点很难更改data 和 h_id,使得hash(key, data_id) 在父节点,仍然有效。
关于排序,您可以简单地假设data 的四个初始字节存储分区的编号——以供以后重建。
编辑:
我可能没有注意到您指出的这个额外存储,但这是我试图提出的。考虑四台机器,A、B、C 和 P,使用初始数据:
P{key, data[3]}
____|____
/ | \
A{} B{} C{}
然后,P 在机器之间分发数据,发送数据分片本身,和生成的哈希:
P{key, data[3]}
____|____
/ | \
A | C
{data[0], hash(key, data[0])} | {data[2], hash(key, data[2])}
B
{data[1], hash(key, data[1])}
如果您假设data[i] 中的第一个字节存储了一个全局索引,那么您可以按照原始顺序重建初始基础data[3]。此外,如果您允许每台机器存储/接收key,您以后可以un 散列data[i] 并在每个本地节点上重建data[3]。
注意添加错误只能发生在数据分片data[i] 和收到的密钥hash(key, data[i]) 上,因为您必须假设key 是全局有效的。这里的要点是hash(key, data[i]) 值的列表也分布在机器之间,而不仅仅是数据分区本身,即您不需要包含所有文件的列表单独存储在任何机器中.
考虑到您有能力在每个节点中维护key,或者至少将key 发送到尝试重建原始数据的一个节点,这里有一个减少步骤的示例,例如,对于节点@987654352 @。 A 和 C 将它们的本地 {data[i], hash(key, data[i])} 发送到节点 B,P 将 key 发送到 B,因此该节点可以un对接收到的数据进行哈希处理:
P{key, data[3]}
|
A | C
{data[0], hash(key, data[0])} | {data[0], hash(key, data[0])}
\ | /
B
{data[1], hash(key, data[1])}
然后,B 计算:
/ {data[1], hash(key, data[1])} \ {data[1]}
unhash( {data[0], hash(key, data[0])} ) => {data[0]} => {data[3]}
\ {data[2], hash(key, data[2])} / {data[2]}
以正确的顺序恢复原始数据。