【发布时间】:2018-06-25 06:50:20
【问题描述】:
MQ服务器收到Put()请求时,哪些因素会影响消息的存储?以下是潜在因素:
1) 在内存中缓存消息一段时间,或者
2) 当收到一定数量的消息时
3) 当收到一定字节阈值的消息时
4) MQ 服务器为每条消息立即保存。
更新
也就是说,当Put()返回时,消息是保存到硬盘还是缓存中,取决于以上因素?
任何信息和官方文档的链接将不胜感激。
下面是一个使用 Put() 的简单场景。
void PutMessages()
{
Open(ConnectionMode.Write);
// putting messages continuously
for (int i = 1; i <= numberOfMsgs; i++)
{
PutMessage(GetMessageInBytes(i));
}
queue.Close();
queueManager.Disconnect();
}
void PutMessage(byte[] messageString)
{
// creating a message object
message = new MQMessage();
message.Write(messageString);
message.Format = MQC.MQFMT_STRING;
message.CharacterSet = 1208;// IbmUtf8Encoding;
message.Persistence = MQC.MQPER_PERSISTENT;
var options = new MQPutMessageOptions
{
Options = false ? MQC.MQPMO_SYNCPOINT : MQC.MQPMO_NO_SYNCPOINT
};
queue.Put(message, options);
}
public void Open(ConnectionMode connectionMode)
{
var connectionSettings = new Hashtable
{
{MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES_MANAGED },
{MQC.CONNECT_OPTIONS_PROPERTY, MQC.MQCNO_RECONNECT }
};
int openOptions = 0;
switch (connectionMode)
{
case ConnectionMode.Read:
openOptions = MQC.MQOO_INPUT_SHARED + MQC.MQOO_FAIL_IF_QUIESCING;
break;
case ConnectionMode.Write:
openOptions = MQC.MQOO_OUTPUT + MQC.MQOO_FAIL_IF_QUIESCING;
break;
}
queueManager = new MQQueueManager(queueManagerName);
queue = queueManager.AccessQueue(queueName, openOptions);
}
public enum ConnectionMode
{
Read,
Write
}
【问题讨论】:
-
持久消息总是在 PUT 返回应用程序之前写入磁盘。持久化意味着消息被持久化到磁盘。如果 put 在同步点下完成,则写入磁盘发生在 COMMIT 而不是 PUT 时,如果 COMMIT 返回,则表示数据已写入磁盘。 MQ 当然是依靠底层操作系统和存储来准确报告数据已写入磁盘,并利用操作系统提供的写入函数来确保数据不会缓存在内存中。列表中的 #1 - #3 与持久消息无关。
-
我想找出持久消息的延迟。可能是在 PUT 返回后,消息可能在存储到硬盘之前已保存到缓存几毫秒。我找不到来自 IBM 的相关文档。
-
如果消息是持久的,put 只会在 MQ 确定已写入磁盘后返回,例如在 linux 上,MQ 使用
O_DIRECT标志打开文件。在 MQ 控制之外,操作系统可能会说它已写入磁盘但实际上并未执行,或者底层 SAN 存储阵列可能会说已写入磁盘但未执行此操作,但在这些情况下,操作系统和存储阵列通常会缓存在电池备份内存中,他们知道有足够的电量在发生电源故障时将缓存刷新到磁盘,但这一切都在 MQ 控制之外。 -
我问的原因是它可能会延迟几毫秒来保存消息以避免通过 MQ 服务器逻辑影响性能,而不是保存每条消息。这发生在 RabbitMq 上。请看stackoverflow.com/questions/49546274/…
-
IBM MQ 不这样做。我正在尝试为您找到链接的引用,但 IBM 一直坚持认为它可以确保消息传递,并且在 PUT(或 COMMIT)调用返回应用程序之前,它会等到写入提交到磁盘。如果应用程序得到了良好的响应,那么它就被写入了。