跳转至主要内容

CAC经常被要求研究VOS消息队列的问题。以下是几个有趣的问题,以及我想与大家分享的一些解决方案和建议。

问题1:最近,一位客户向我们提出了一个问题。一个请求者无法将消息添加到消息队列中,收到错误代码e$max_file_exceeded.奇怪的是,队列是空的,如list_messages命令所示。奇怪的是,队列是空的,如list_messages命令所示。

经过对队列的检查,可以看到该队列使用的磁盘块数已经接近非扩展文件的最大文件大小。

名称:%s1#d01>AppData>queue.MQ。

文件组织:消息队列文件
最后使用时间 11-08-16 14:45:13 edt
最后修改于 11-08-16 14:45:13 Edt
最后保存时间:10-06-14 21:34:18 10-06-14 21:34:18 edt
创建时间:10-06-09 11:03:15 10-06-09 11:03:15 EDT
交易文件:是
日志保护:无
安全开关:无
审计:无
动态扩展:无
范围大小:1
最后一条信息。 51689380
块使用。 520201

为什么这个队列既满了,又空了?

在过去的某个时候,负责将消息从队列中排出的服务器离线了。这导致了大量信息的积压。这些消息最终被服务器处理并从队列中删除。当消息从队列中删除时,队列的_record_index索引中会添加一个键,键值表示被删除消息的字节数。 当一条新的消息被添加到消息队列中时,文件系统会试图找到一条之前被删除的消息,其大小与新消息的大小一致。如果找不到,新的信息就会被写入队列末尾的空白处。

在这种情况下,队列中没有足够的处女空间来容纳新的消息,也没有正确大小的已删除消息。

这个故事的寓意是,限制任何给定队列中唯一的消息长度的数量是个好主意。与其让每条消息使用它所需要的确切字节数,不如将数值四舍五入到某个标准大小。通过使用这种技术,你增加了新消息可以重复使用以前删除的消息的空间的机会。

问题2:最近,在消息队列的性能方面出现了另一种情况。一个客户说,清空一个有40多万条消息的消息队列所需的时间太长了。

他们最近遇到了一个问题,即他们的服务器进程无法及时处理消息队列中的消息。幸运的是,请求者一直在运行,因此没有数据丢失。当服务器问题解决后,他们已经过了很多小时才赶上积压的请求,然后可以开始处理最近的交易。客户在问为什么会出现这种情况,以及在今后的情况下如何防止或加快处理速度。

当消息队列中的消息被删除时,系统维护的_record_index中会增加一个键,其中键的值就是消息的长度。如果被删除的消息与之前被删除的消息长度相同,则未使用的数据位置会被保存为包含该消息大小的键上的重复条目,位于重复值列表的最后。因此,如果有几十万条被删除的消息,都是相同大小的(或者被删除的消息长度集很小),重复键列表就会非常长,删除一条消息的时间就会线性上升。

相反,当一个消息被添加到队列中,并且存在一个消息长度的_record_index键时,最新删除的记录所占用的空间被重新使用,以包含新消息的数据。然后,这个值必须从包含消息长度的键值中删除。因此,添加消息的时间是线性上升的;删除的消息越多,添加新消息的时间就越长。

这个故事的寓意是,系统维护的消息队列中的数据是有记忆的;队列会记住所有以前消息的位置和大小。即使在队列被清空后,这些信息也会持续存在。尽量避免让你的消息队列发展到一个巨大的规模(几万或几十万个磁盘块)。否则,你会发现向队列添加和删除消息的成本会随着时间的推移而增加。

这两种情况的解决办法都是一样的。

解决方案 A:消息队列可以在打开的同时被截断,可以使用例程 s$truncate_queue 来实现。例程s$truncate_queue可以用来完成这个任务。但是,有4个条件必须满足。

1:必须没有请求者保持消息队列的开放状态

2:消息队列中的所有消息必须被排空

3:这个例程必须由服务器调用。

4:队列不能是事务文件。

如果前3个条件不满足,s$truncate_queue将返回e$no_truncate_queue。如果最后一个条件不满足,s$truncate_queue将返回e$invalid_io_operation。

解决方案B:如果应用设计允许拥有多个服务器,可以定期重命名现有的消息队列,用正确的名称创建一个新的消息队列,启动一组新的服务器,并弹出请求者。当服务器启动时,它们将在一个新的,但空的消息队列上开始处理。当请求者启动时,他们将把自己的请求添加到新的、空的消息队列中。原有的一组服务器可以继续运行,处理积压的请求,直到队列为空。然后可以停止旧的一组服务器,并删除旧的消息队列。

此外,问题1的一个解决办法可能是使用基于范围的消息队列。这将允许在队列中放置额外的消息,因为最大的文件大小将大于范围大小的一个系数。然而,通过使用范围消息队列,如果或当消息队列在任何一个时间点包含大量消息时,性能将比正常情况更差。

如前所述,限制任何给定队列中唯一消息长度的数量,将提高新消息能够重新使用之前删除的消息所释放的空间的概率。这将有助于解决本帖中提到的两个问题。

© 2024Stratus Technologies.