我有一些数据库项目,除了主键之外,还需要项目所属组的唯一索引。我们来调用属性nbr
,以及将项目分组在一起并定义唯一范围的属性nbr
:我们会打电话group
. This nbr
必须在 [1-N] 范围内,并且may从外部源导入项目时进行设置。由于所有项目都必须有一个nbr
,任务就变成了如何跟踪使用了哪些值,以便能够选择一个免费的nbr
对于手动添加的新项目。
我正在使用 DynamoDB 和 Redis。我无法建立 DynamoDB 索引nbr
。到目前为止,我的想法是使用 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,可能分为子集。预填充 Redis,全部免费nbr
1-N 看起来很丑。
假设 N 的量级为 65536。
出于性能或其他原因,上述解决方案是否更好/更差?有没有更好/更聪明的方法,也许利用我不知道的 Redis 的一些聪明的方面?
Edit:
凯文的回答产生了以下解决方案(伪代码):
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 https://redis.io/topics/data-types-intro#bitmaps记录一切可能nbr
,是否使用该值?
要记录某个值被采用,请使用SETBIT https://redis.io/commands/setbit:
SETBIT key [nbr] 1
寻找一个免费的nbr
use BITPOS https://redis.io/commands/bitpos:
BITPOS key 0
为了避免竞争条件,您需要确保您的获取和设置是原子的。 [OP 解决了这个问题后续问题 https://stackoverflow.com/questions/54568723/redis-bitset-and-watch/54574209.]
这将需要很少的内存(65536 个可能的值需要 8K 字节)。BITPOS
是 O(n),但这不太可能是一个真正的问题。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)