如何在hadoop集群上处理id生成?

如何在hadoop集群上处理id生成?,hadoop,mapreduce,partitioning,Hadoop,Mapreduce,Partitioning,我正在hadoop集群上构建一个字典,需要为每个令牌生成一个数字id。我该怎么做 您有两个问题。首先,您要确保为每个令牌分配一个id。要做到这一点,您应该按标记对记录进行排序和分组,并在减速机中进行赋值。一旦确保每个令牌只调用一次reducer方法,您就可以使用上下文中的分区号和reducer维护的唯一数字id(每个分区一个实例)-只需在setup方法中使用一个初始化为1并在reduce方法中递增的实例变量 为了避免不属于业务逻辑的同步、排序和分组,您可以使用一些技巧,这些技巧会更快 最简单的方

我正在hadoop集群上构建一个字典,需要为每个令牌生成一个数字id。我该怎么做

您有两个问题。首先,您要确保为每个令牌分配一个id。要做到这一点,您应该按标记对记录进行排序和分组,并在减速机中进行赋值。一旦确保每个令牌只调用一次reducer方法,您就可以使用上下文中的分区号和reducer维护的唯一数字id(每个分区一个实例)-只需在setup方法中使用一个初始化为1并在reduce方法中递增的实例变量

为了避免不属于业务逻辑的同步、排序和分组,您可以使用一些技巧,这些技巧会更快

最简单的方法是在Reducer中生成UUID,每个键一个UUID.randomUUID(),但它们不是数字

如果您想要连续的数字ID序列,并且您的输出足够小,可以通过org.apache.hadoop.mapreduce.job.setNumReduceTasks(int任务)为作业强制使用一个减缩器,因此所有键都将指向一个减缩器

如果映射器的输出对于单个Reducer来说仍然太大,并且您不关心id的序列连续性,或者您的字典可以被分区,那么您可以对分区器()使用一些技巧。其思想是,您可以在逻辑上将密钥划分为N个已知长度的范围(例如,范围1可以有1 mil的密钥以1开头,范围4可以有500个ID以3500000开头,等等)。逻辑:

  • 将减速器的数量设置为N(JobConf.setNumReduceTasks(N))
  • 实现将键与其范围匹配的分区器,它将把同一范围内的所有键指向同一个减速器
  • 在Reducer中有一个以范围的第一个id开头的计数器(在reduce的第一次调用时,使用与partitioner中相同的逻辑来标识哪个范围是Reducer)
  • 如果您对范围没有任何业务知识,您可以花一些时间对键进行区分,并计算范围及其长度。通过这个,您可以在结果集中获得连续的ID序列

    如果您不想花时间进行关键点区分,那么目标是为每个具有不同数字的减速机启动ID(减速机1生成的ID仅以1(1,10,124523,1341243)开头,减速机2以2(2,23,234532)开头,等等)。 为此,计算键的第一个字节的mod 10,强制10个减数,将零指向与1相同的分区(主要原因是没有以0开头的2位整数,这可能会导致与其他分区的ID冲突),因此分区0的输出为空。在减速机端,将计数器附加(连接2个字符串!!!)到(键mod 10的第一个字节),其中0更改为1。每个reducer都有一个从1到无穷大的计数器,可以从包含该分区最后一个id的文件初始化

    因为所有键都以不同的数字开始,所以它们从不重叠,因此不需要在多个还原器之间同步。它由mod结果和计数器的字符串串联保证,因此不会溢出到下一个前缀/前导数字。 另一个优点是您不需要做任何预排序,这不是您业务逻辑的一部分。 当Reducer关闭时,它可以将id生成中使用的最后一个计数器写入一个文件,该计数器可以在下一次运行中使用,并通过字典的分区提供id的连续性

    要将分区数从10增加到100,请使用mod 100并将一位数结果与两位数结果合并(我们再次浪费了10个减缩器的输出)。例如10%100=10,1%100=1转换为10,102%100=2转换为20,方法是将“0”添加为字符串或乘以10。目标是使所有前缀具有相同的位数,在本例中为2

    通过巧妙的逻辑,我们可以避免浪费跳过的分区(在mod 100的情况下为0或1,2,9)

    警告:此逻辑易受数据倾斜的影响

    我希望有帮助,
    干杯。

    我们使用的另一个选项是将ID块分配给任务,为此,您需要一种机制来管理事务。我们使用AWS的SimpleDB来跟踪已使用或未使用的事务和ID

    在作业开始时,我们将整个ID块集锁定在简单DB上(只有一个属性更改为“锁定”),然后每个任务调用简单DB“签出”它使用的ID块

    如果任务失败,它永远不会“解锁”块,也不会更新上次使用的ID,因此这些ID不会被失败的任务使用。最后,当我们解锁整个ID块集时,我们将解锁失败任务保留的所有ID块

    我们将通过从simple DB导入/导出ID块来改进此过程,这样就不必更新外部资源。相反,我们可以从与数据一起存储的文件中读取可用ID,将其写入简单db,使用简单db协调将块分配给各个任务(映射器、还原器),然后成功地将它们写回

    一旦我们做了改进,我们可能会公开代码,所以如果有人对这种方法感兴趣,请随时与我联系,如果我们完成了,我会用代码更新这篇文章

    key = "abc", ascii of 'a' is 97, 97 % 10 = 7 and id for that key is '7' + '1' = '71', 
    for "asd" it will be '7' + '244' = '7244', 
    for "bbv" is '8' + '1' = '81', 
    for "bgh" is '8' + '2' = '82', 
    for "ddv", 'd' is ascii 100, 100 % 100 = 0 , convert to 1, '1' + '1' = '11', 
    for "edv" is 101 % 100 = 1, '1' + '2234' = '12234'.