【发布时间】:2023-04-08 03:55:01
【问题描述】:
我有数据库项目,除了它们的主键外,还需要一个对项目所属组唯一的索引。我们将属性称为nbr,将项目组合在一起并定义唯一nbr 的范围的属性我们将称为group。 nbr 必须在 [1-N] 范围内,并且可以在从外部源导入项目时设置。由于所有项目都必须有一个nbr,因此任务就变成了如何跟踪使用了哪些值,以便为手动添加的新项目选择一个免费的nbr。
我正在使用 DynamoDB 和 Redis。我无法在 nbr 上创建 DynamoDB 索引。到目前为止,我的想法是使用 Redis 跟踪哪些数字已用于特定组,这样对于 Redis 键,例如 <MYGROUP>-item-nbrs,我可以存储所有使用的 nbr:s 并实现逻辑来查找下一个免费nbr。使用的nbr 范围内的孔是可以接受的,但在考虑用尽数量之前应填充孔。
基本上我想找到一个最大大小为 N 的稀疏数组的未使用索引。
将这些信息存储在 Redis 中以快速找到免费的nbr 的良好结构是什么?到目前为止,我的想法包括:
按排序顺序包含所有使用的 nbr 的单个逗号分隔字符串?为了找到一个空闲的 nbr,发出一个
GET命令并解析字符串,直到找到一个洞或列表的末尾,选择的号码被插入到字符串中,然后整个字符串被替换。当 N 很大时,这似乎非常低效。每个使用
nbr的哈希存储为自己的字段,并使用例如HSCAN遍历哈希字段以找到免费的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 的一些聪明方面?
编辑:
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
}
}
【问题讨论】:
标签: algorithm redis sparse-matrix