延迟队列是一个队列,其中每条消息都有一个与之关联的延迟时间,并且只有在其延迟到期时才能获取消息。队列的头部是那个过去延迟到期的消息。如果没有延迟到期,则没有头,而且dequeue将返回null。
实际上,我正在使用Azure编写云应用程序,而在Azure中,只有FIFO队列可用,而不是优先级/延迟队列。所以我来到这里看是否有人可以给我一些指示,从我可以从正确的方向开始。我google了很多,但只发现了Java中的延迟队列实现,而且没有关于延迟队列的标准教程/研究论文。
修改
我的代码是什么?
实际上,我必须首先设计这些东西并将它呈现给我的经理,一旦我们完成设计,那么只有我才能开始编码。
有关该方案的更多详细信息
它是一个基于主/从模型的分布式应用程序。主服务器生成消息并将它们放入Azure Service Bus队列,并且有多个从服务器(在多台计算机上运行)从队列中读取并进行处理。如果主机发生故障,则其中一个从机充当主机并开始生成消息。我不想在主服务器中存储任何状态信息,因为如果主服务器发生故障,所有状态信息也会随之消失。
答案 0 :(得分:9)
Windows Azure队列消息在将消息插入队列时指定了延迟(以秒为单位)。在达到超时延迟之前,将不会显示消息。请参阅this MSDN article以查看API详细信息。
隐身超时也在各种语言SDK实现中实现。由于您使用的是C#,AddMessage()
调用的内容如下所示。请注意AddMessage()
的第3个参数指定隐身超时:
var acct = CloudStorageAccount.DevelopmentStorageAccount;
var queueClient = acct.CreateCloudQueueClient();
var queue = queueClient.GetQueueReference("myqueue");
queue.CreateIfNotExist();
var msg = new CloudQueueMessage("test message");
queue.AddMessage(msg, TimeSpan.FromHours(2), TimeSpan.FromMinutes(30));
答案 1 :(得分:3)
首先,我们需要实现优先级队列。这是我不久前写的一篇。这可能不太理想;它有一个很小的API,它可能表现得更好,但它是一个充分的起点:
public class PriorityQueue<TPriority, TElement>
{
SortedDictionary<TPriority, Queue<TElement>> dictionary = new SortedDictionary<TPriority, Queue<TElement>>();
public PriorityQueue()
{
}
public Tuple<TPriority, TElement> Peek()
{
var firstPair = dictionary.First();
return Tuple.Create(firstPair.Key, firstPair.Value.First());
}
public TElement Pop()
{
var firstPair = dictionary.First();
TElement output = firstPair.Value.Dequeue();
if (!firstPair.Value.Any())
dictionary.Remove(firstPair.Key);
return output;
}
public void Push(TPriority priority, TElement element)
{
Queue<TElement> queue;
if (dictionary.TryGetValue(priority, out queue))
{
queue.Enqueue(element);
}
else
{
var newQueue = new Queue<TElement>();
newQueue.Enqueue(element);
dictionary.Add(priority, newQueue);
}
}
}
在包装时,延迟队列很简单:
public class DelayQueue<T>
{
private PriorityQueue<DateTime, T> queue = new PriorityQueue<DateTime, T>();
public void Enqueue(T item, int delay)
{
queue.Push(DateTime.Now.AddMilliseconds(delay), item);
}
public T Dequeue()
{
if (queue.Peek().Item1 > DateTime.Now)
return queue.Pop();
else
return default(T);
}
}
答案 2 :(得分:0)
如何使用两步过程构建队列以使项目出列。这是高级流程:
将FIFO队列中的第一项出列队列;将其隐形设置为N分钟(无论您决定隐形应该是什么) - 这允许您使项目在一段时间内不可见,就像它在队列中不存在一样。这是我所指的NextVisibleTime属性。
检查DequeueCount属性 - 如果出队计数为0,则该项目第一次出列。忽略该项目并继续前进。由于它的隐身性已设定,因此在它出现之前不会再次取出它。如果出队计数为1或更大,则它出列一次,并且必须在所需的时间内设置为不可见。
这应该允许您实现延迟队列。我也可以想到其他方法。例如,队列中的每个项目都是创建时间;这可用于动态计算项目需要保持不可见的时间。要更改属性的隐身,请选中以下方法:http://msdn.microsoft.com/en-us/library/microsoft.windowsazure.storageclient.cloudqueue.updatemessage.aspx