我们有5台服务器,每台服务器运行相同的服务,生成std::map
。 std::map
中的每个项目都由一个唯一的整数作为键,double作为其对应的值。为了检查不同机器之间的一致性,我们需要不断检查五台服务器中std::map
的相等性。
每个std::map
存储了2百万个不同的商品,并且在白天不断变化。比较该值的天真方法如下:
compare S1 with S2, S3, S4, S5
compare S2 with S3, S4, S5
compare S3 with S4, S5
compare S4 with S5
这是N * N复杂度,只要地图中的单个值发生变化,就必须重做O(N)比较。
更好的想法是为每个地图构建一个签名,最后将地图比较简化为浮点数比较。这里有两个挑战:
任何建议都表示赞赏。
答案 0 :(得分:2)
由于地图显然总是一致的,因此自然会发生相同的修改以相同的顺序发生。
这意味着您可以使用修改序列的(安全)哈希来代替比较地图本身。对于每次修改,您都会更新H = hash(H | Key | Value )
,然后比较H1
... H5
。
H的初始选择并不重要,主要要求是所有服务器应以相同的H值开始,并且映射处于相同的状态。
答案 1 :(得分:1)
根据Bryan Chen的评论,可以递增计算的简单哈希如下:
给定哈希函数h()计算h(len(k)|| k || v)其中||表示追加,len(k)是k的长度,k和v是单个键值对的键和值。然后跟踪哈希映射中所有键值对的总和或xor,在添加或删除键值对时通过递增,递减或对其进行维护来保持它。
对于知道或可以找到h(len(k)|| k || v)哈希值对的对手来说当然不安全。在其他情况下,如果h()可以建模为一个想法随机函数,它似乎是安全的 - 但在其他人看过这个想法之前我不会打赌这个。如果您担心,可以使用http://en.wikipedia.org/wiki/Hash-based_message_authentication_code和密钥来获取秘密h()。
答案 2 :(得分:0)
增量哈希显然是要走的路。
除非出于某种原因,否则不是。另一种方法是序列化和散列整个树。 Boost提供了方便的序列化功能,并且有一个可用的MD5哈希生成器here。将这两者结合起来,您可以随时对任何地图进行哈希处理。下面的代码将编译为:
g++ test.cpp md5.cpp --std=c++11 -lboost_serialization
当然,您可以将MD5哈希替换为您选择的其他哈希值。
#include <map>
#include <sstream>
#include <iostream>
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/map.hpp>
#include <boost/archive/text_oarchive.hpp>
#include "md5.h"
int main()
{
std::map<int, int> map = {{1,2}, {2,1}};
std::stringstream ss;
boost::archive::text_oarchive oarch(ss);
oarch << map;
std::cout<<md5(ss.str())<<std::endl;
}