如何有效地在键值存储上建模队列?

时间:2014-01-13 15:40:30

标签: queue key-value key-value-store

假设我有一个键值数据库,我需要在它上面构建一个队列。如何在不表现糟糕的情况下实现这一目标?

一个想法可能是将队列存储在数组中,并使用固定密钥存储数组。这是一个非常简单的实现,但非常慢,因为每次读取或写入访问都必须加载/保存完整的数组。

我还可以使用随机键实现链表,并且有一个固定键作为元素1的起点。根据我是喜欢快速读取还是快速写入访问,我可以指出固定的元素到队列中的第一个或最后一个条目(所以我必须前进/后退)。

或者,为了继续 - 我还可以有两个固定的指针:一个用于第一个,用于最后一个项目。

有关如何有效执行此操作的任何其他建议?

2 个答案:

答案 0 :(得分:1)

我认为这取决于您要实现的队列类型,并且没有任何解决方案是完美的,因为键值存储不是此类任务的正确数据结构。总会有某种黑客入侵。

对于一个简单的先进先出队列,您可以使用一些kev值存储,如下面的内容:

{
     oldestIndex:5,
     newestIndex:10
}

在此示例中,队列中将有6个项目(5,6,7,8,9,10)。项目0到4已经完成,而现在没有项目11左右。生产者工作者将增加newestIndex并将其项目保存在密钥11下。消费者使用密钥5下的项目并增加oldestIndex。

请注意,如果您有多个使用者/生产者,并且队列从不为空,则此方法可能会导致问题,因此您无法重置索引。

但多线程问题也适用于链表等。

答案 1 :(得分:1)

最初,键值结构与原始内存存储非常相似,其中计算机内存中的物理地址作为键。因此,任何类型的数据结构都可以确定地模拟键值存储,包括链表。

最初,链表是包含前一节点或后续节点的索引信息的节点列表。然后,它自身的节点也应被视为子键值结构。使用密钥的附加前缀,节点中的信息可以单独存储在键值对的平面表中。

为了继续,键的特殊后缀也可以摆脱冗余指针信息。这个假装列表可能如下所示:

pilot-last-index: 5
pilot-0: Rei Ayanami
pilot-1: Shinji Ikari
pilot-2: Soryu Asuka Langley
pilot-3: Touji Suzuhara
pilot-5: Makinami Mari

我认为相应的算法也是可以想象的。如果您可以使用守护程序线程来操作这些键,则可以在上面的示例中将pilot-5重命名为pilot-4。即使在某些特殊情况下不允许有额外的线程,它自己的队列结果也不会受到影响。只有一些开销会依次存在断点。

然而,应该应用上述两个中的哪一个是存储空间成本或CPU时间开销之间的平衡问题。

线程安全是一个问题,但这是一个古老的问题。就像在JDK中实现ConcurrentMap接口的类一样,也可以完美地提供对键值数据的Atomic操作。在某些键值中间件中也有类似的方法,比如memcached,它可以让你分别更新键或值并安全地进行线程化。然而,这些实现是algrithm问题​​,而不是它自己的键值结构。