当前位置: 首页 > 面试题库 >

使用Redis在有限范围内生成唯一ID

祁杰
2023-03-14
问题内容

我有一些数据库项目,除了它们的主键外,还需要一个索引,这些索引对于项目所属的组是唯一的。让我们称之为属性nbr,该属性将各项组合在一起并定义unique的范围nbr:s,我们称之为group。该值nbr必须在[1-N]范围内,并且
可以
在从外部来源导入项目时进行设置。由于所有项目都必须有一个nbr,因此任务将变成如何跟踪使用哪些值的功能,以便nbr为手动添加的新项目选择免费的项目。

我正在使用DynamoDB和Redis。我无法在上创建DynamoDB索引nbr。到目前为止,我的想法是使用Redis跟踪用于特定组的数字,以便为Redis密钥(例如,<MYGROUP>-item- nbrs我可以存储所有used
nbr:s并实现逻辑以查找下一个free)nbr。在使用范围内的nbr孔是可以接受的,但是在考虑用完的数量之前,应先填充孔。

本质上,我想找到最大大小为N的稀疏数组的未使用索引。

在Redis中存储此信息以快速找到免费信息的良好结构是nbr什么?到目前为止,我的想法包括:

  • 所有用过的nbr的单个逗号分隔字符串(按排序顺序)?要找到一个免费的nbr,发出GET命令并解析该字符串,直到找到一个空洞或列表的末尾,然后将所选择的数字插入该字符串中,然后替换整个字符串。当N大时,这似乎效率很低。

  • 每个使用的哈希nbr存储为自己的字段,并使用例如HSCAN遍历哈希的字段以找到一个free nbr。当N大时,HSCAN必须扫描很多字段。

  • 将我的nbr:s划分为称为p1-20,p21-40,p41-60等的字段,每个字段仅包含该分区内的一组使用过的nbr:s,并且在分区耗尽时不再使用(不再可用nbr: s),将其完全删除以加快进一步的迭代速度。使用HSCAN进行迭代,然后使用HSET启动新分区。

  • 存储所有可用空间nbr而不是所有可用空间,并使用排序后的集合和ZPOPMIN或常规列表和LPOP(可能会划分为子集)。不过,使用所有免费的nbr1-N 预先填充Redis 似乎很丑。

假设N的大小为65536。

由于性能或其他原因,上述解决方案是否更好/更坏?有没有更好/更聪明的方法,也许是利用了我不知道的Redis的一些巧妙方面?

编辑:

凯文的答案导致了以下解决方案(伪代码):

function getFreeNbr() {
  while (true) {
    send "WATCH numbers"
    nbr = send "BITPOS numbers 0"

    if nbr < N
      send "MULTI"
      send "SETBIT numbers $nbr 1"
      if send "EXEC" != NULL
        return nbr
      end if
    else 
      send "UNWATCH numbers"
      return -1
    end if
  }
}

问题答案:

如何使用位图来尽可能记录nbr是否使用该值?

要记录使用的值,请使用SETBIT

SETBIT key [nbr] 1

要免费nbr使用BITPOS

BITPOS key 0

为了避免比赛条件,您需要确保获取和设置是原子的。OP在后续问题中解决了这个问题

这将需要很少的内存(8K字节用于65536个可能的值)。BITPOS是O(n),但这不太可能是一个真正的问题。



 类似资料:
  • 问题内容: 我需要生成一个范围内的随机唯一数字吗?怎么做 ? 我可以通过生成随机数 我知道这段代码不好,所以我需要一个更好的优化版本代码!帮帮我 ! 例如:如果我需要在1到15之间生成3个数字,它们应该像5、9、1而不是3,1,2 [具有1-3(我要生成的数字)] 问题答案: 以随机顺序排列数字范围的数组: 包装功能: 例: 结果:

  • 问题内容: 我知道如何在Python范围内生成随机数。 我知道我可以将其循环生成n个数量的这些数字 但是,我需要确保该列表中的每个数字都是唯一的。除了大量的条件语句之外,还有一种直接的方法可以生成n个唯一的随机数吗? 重要的是列表中的每个数字都不同。 所以 [12,5,6,1] =好 但 [12,5,5,1] =不好,因为数字5出现两次。 问题答案: 如果您只需要采样而无需更换: random.s

  • 我目前正在创建一个应用程序,它将生成随机数。所以每次它都会生成三个数字num1、num2和num3。这些数字不应该重复。例如,如果num1=1,则num2和num3不能等于1。我尝试过此代码,它将显示0-2之间的三个不同数字。然而,我想生成1-3、2-4、3-5等范围内的随机数。因此,我如何通过使用下面的代码来实现这一点。请帮帮我,因为我是新手。非常感谢。

  • 我试图在两者之间生成一个随机的双倍,但不包括它的下界和上界(lower,upper)。我见过很多关于从生成一个数字的问题,包括它的下界,但不包括它的上界[lower,uper),但它们没有回答我的问题,因为它们没有解决这个问题。 我想出了两个“解决方案”来解决这个问题,但对任何一个都不满意。 虽然这几乎每次都能在第一次尝试时给出一个有效的结果,但它似乎不一致且笨拙,而且在rng返回0.0的可能性很

  • 我还没有找到一个函数来生成给定长度的随机浮点数数组。 我已经看过随机抽样,但似乎没有函数可以满足我的需求。 random.uniform很接近,但它只返回一个元素,而不是一个特定的数字。 这就是我所追求的: 这将返回一个由50个随机非唯一浮点数(即:允许重复)组成的数组,这些浮点数均匀分布在范围内。 有这样的功能吗

  • 返回指定范围内的一个随机数。 使用 Math.random() 生成一个随机值,使用乘法将其映射到所需的范围。 const randomNumberInRange = (min, max) => Math.random() * (max - min) + min; randomNumberInRange(2, 10); // 6.0211363285087005