从大范围的数字中分配数字的最佳解决方案是什么?

时间:2017-01-17 03:54:22

标签: python mongodb algorithm

需求说明

有一个数字为1 - 160 000 000的游泳池。

创建obj时,需要为obj分配一个数字。有一些规则

  1. 池中的数字
  2. 其他obj未采用的号码
  3. 用户有时也会指定一个用于创建obj的数字。

    下面是一些解决方案,每个都有自己的问题,所以我希望有一些更好的解决方案

    请注意我们在这里使用mongo DB。我不想更改数据库,因为这是一个问题。

    解决方案1 ​​

    生成一个包含160,000,000个项目的大表(集合)。 该集合的结构是

    number,allocated
    

    分配号码时,使用find_one_and_update方法更新一条记录,将分配的值从false更改为true

    问题

    此解决方案的问题是生成160,000,000的集合太重

    解决方案2

    与解决方案1类似,但我们一次不生成160,000,000。相反,我们每次生成1000。当这1000条记录用完时,我们再生成1000条

    问题

    问题是用户有时可以指定数字。例如,我们在集合中生成1000条记录,但是使用想要使用数字5000。所以这就是问题,因为我们没有生成它

    解决方案3

    每次我们创建一个obj时,我们会在1-160,000,000之间为该obj生成一个随机数,并将其保存在数据库中。

    问题

    很难避免先前未使用您生成的随机数

1 个答案:

答案 0 :(得分:1)

通常的方法是使用(Sharded)原子计数器。计数器最初的值为零。当需要索引时,应该调用一个API,它将自动递增此计数器并给出其旧值。

虽然这可能比您提到的方法快得多,但根据您的需要,这可能仍然不够快。上述情况中的瓶颈是在使增量原子化时通常使用的单锁。这在某些分布式情况下并不理想。

使用分片计数器

在这种分布式方案中提高性能的常用方法是使用分片计数器:

  1. 对计数器进行分片(将值1..160,000,000的范围划分为N个不相交的范围。)
  2. 在具有N个不同锁的N个线程/进程/实体/机器中运行相同的原子增量服务。
  3. 基于某些属性(可能是对象的地址或对象的散列),选择其中一个范围(在分布式系统中,您可以使用分布式散列)
  4. 询问(2)中提到的适当服务以获取下一个索引。
  5. 上述内容会提高性能N - 折叠,可能会扩展到您的应用需求。

    关于分片计数器的一些有趣读物是link

    请注意,如果要使用随机数生成(解决方案3),则可以使用Bloom Filters优化查找密钥的存在。根据您的性能需求,这可能就足够了。