C++ 如何为不断变化的'std::map'计算签名`

C++ 如何为不断变化的'std::map'计算签名`,c++,algorithm,C++,Algorithm,我们有5台服务器,每个服务器都运行相同的服务,该服务生成std::map。std::map中的每个项都由一个唯一的整数作为键和一个双精度作为其对应值组成。为了检查不同机器之间的一致性,我们需要不断检查五台服务器之间的std::map是否相等 每个std::map存储200万个不同的项目,并且在一天中不断变化。比较值的简单方法如下所示: compare S1 with S2, S3, S4, S5 compare S2 with S3, S4, S5 compare S3 with S4, S5

我们有5台服务器,每个服务器都运行相同的服务,该服务生成
std::map
std::map
中的每个项都由一个唯一的整数作为键和一个双精度作为其对应值组成。为了检查不同机器之间的一致性,我们需要不断检查五台服务器之间的
std::map
是否相等

每个
std::map
存储200万个不同的项目,并且在一天中不断变化。比较值的简单方法如下所示:

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)比较

更好的方法是为每个映射构建一个签名,最后将映射比较简化为浮点数比较。这里有两个挑战:

  • 如何基于巨大的地图构建单一价值
  • 如何根据不断变化的贴图增量计算此值

  • 欢迎提出任何建议。

    根据Bryan Chen的评论,可以增量计算的简单哈希如下:

    compare S1 with S2, S3, S4, S5
    compare S2 with S3, S4, S5
    compare S3 with S4, S5
    compare S4 with S5
    
    给定散列函数h()计算h(len(k)| | k | | v),其中| |表示附加,len(k)是k的长度,k和v是单个键值对的键和值。然后跟踪哈希映射中所有键值对的和或异或,在添加或删除键值对时通过对其进行递增、递减或异或来维护它


    对于知道或能够找到散列值对的h(len(k)| | | k | | v)的对手来说,当然不安全。在其他情况下,如果h()可以建模为idea随机函数,那么它看起来是安全的——但在其他人看到这个想法之前,我不会在这方面下太多赌注。如果您担心,您可以使用一个密钥来获得一个秘密h()。

    由于映射显然总是一致的,因此自然会以相同的顺序进行相同的修改

    这意味着您可以使用修改序列的(安全)散列来代替比较映射本身。对于每次修改,您更新
    H=hash(H | Key | Value)
    ,然后比较
    H1
    H5


    H的初始选择并不重要,主要要求是所有服务器都应该以相同的H值开始,并且映射处于相同的状态。

    增量哈希显然是一种方法

    除非,不管出于什么原因,它不是。另一种方法是序列化和散列整个树。Boost提供了一个方便的序列化函数,并且有一个MD5哈希生成器可用。将这两者结合起来,可以随时对任何映射进行哈希运算。下面的代码将编译为:

    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;
    }
    
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括“md5.h”
    int main()
    {
    map={1,2},{2,1};
    std::stringstream-ss;
    boost::archive::text_oarchive oarch(ss);
    
    oarch应该只检测意外的去同步,还是也能击败智能对手?如果S1==S2,S1==S3,S1==S4,S1==S5,那么所有的都是相等的O(N)。如果不是,则将它们视为巨大的复合键,并对它们进行排序,将它们分成O组(N log N)