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

Use Redis to generate unique ID from a limited range

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

我正在使用 DynamoDB 和 Redis。我无法在 nbr 上创建 DynamoDB 索引。到目前为止,我的想法是使用 Redis 来跟踪哪些数字已用于特定组,因此对于诸如 <MYGROUP>-item-nbrs 之类的 Redis 键,我可以存储所有使用过的 nbr:s 并实现寻找下一个空闲 nbr 的逻辑。已用 nbr 范围内的空洞是可以接受的,但在考虑用尽数字之前应先填补空洞。

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

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

假设 N 的大小为 65536。

以上任何解决方案 better/worse 是否出于性能或其他原因?有没有 better/smarter 方法,也许可以利用 Redis 的一些我不知道的聪明方面?

编辑:

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

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
  }
}

使用 Bitmaps 来记录每个可能的 nbr 是否使用该值如何?

记录一个值被使用 SETBIT:

SETBIT key [nbr] 1

要找到免费的 nbr 使用 BITPOS:

BITPOS key 0

为避免竞争条件,您需要确保您的获取和设置是原子的。 [OP 在 中解决了这个问题。]

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