Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Msmq 寻找消息总线实现,它提供了介于全ACID和无ACID之间的功能_Msmq_Message Queue_Distributed Transactions_Denormalization - Fatal编程技术网

Msmq 寻找消息总线实现,它提供了介于全ACID和无ACID之间的功能

Msmq 寻找消息总线实现,它提供了介于全ACID和无ACID之间的功能,msmq,message-queue,distributed-transactions,denormalization,Msmq,Message Queue,Distributed Transactions,Denormalization,有谁知道消息总线实现提供了对一致性保证的细粒度控制?全酸太慢,没有酸太错 我们目前正在使用Rhino ESB包装MSMQ进行消息传递。在对分布式事务使用持久的事务性消息传递时,MSMQ在等待I/O完成时会在相当长的时间内阻止提交 我们的消息分为两大类:业务逻辑和非规范化。后者占消息总线通信量的很大比例 业务逻辑消息需要全ACID的保证,MSMQ已被证明足以满足这一要求 非规范化消息: 必须耐用 必须在原始事务完成后才能处理 可以处理多次 即使原始事务回滚,也可以进行处理,只要遵守2) (在某些特

有谁知道消息总线实现提供了对一致性保证的细粒度控制?全酸太慢,没有酸太错

我们目前正在使用Rhino ESB包装MSMQ进行消息传递。在对分布式事务使用持久的事务性消息传递时,MSMQ在等待I/O完成时会在相当长的时间内阻止提交

我们的消息分为两大类:业务逻辑和非规范化。后者占消息总线通信量的很大比例

业务逻辑消息需要全ACID的保证,MSMQ已被证明足以满足这一要求

非规范化消息:

  • 必须耐用
  • 必须在原始事务完成后才能处理
  • 可以处理多次
  • 即使原始事务回滚,也可以进行处理,只要遵守2)
  • (在某些特定情况下,耐久性要求可能会放宽,但将这些情况视为例外情况加以识别和处理会增加复杂性。)

    所有非规范化消息都是在过程中处理的,因此不需要IPC

    如果流程重新启动,则可以假定所有事务都已完成(提交或回滚),并且必须恢复所有尚未处理的非规范化消息。可以重播已处理的非规范化消息

    据我所知,处理事务的消息传递系统倾向于在全ACID或无ACID之间进行选择,ACID会带来性能损失。我们看到对TransactionScope#Commit()的调用在某些情况下需要数百毫秒,具体取决于发送的消息数量

    使用非事务性消息队列会导致消息在其原始事务完成之前被处理,从而导致一致性问题

    我们系统的另一个部分具有相似的一致性要求,但复杂性较低,它已经使用了类似于事务日志的自定义实现,概括起来,对于这个用例来说,这当然是一个选项,但我不希望实现低延迟、并发、持久、,事务性消息传递系统(如果不必):P


    如果有人想知道的话,要求非规范化消息的持久性的原因是检测和修复去同步可能会非常困难,也可能非常昂贵。人们确实会注意到出现了一些小问题,而页面刷新无法修复这些问题,因此忽略desyncs不是一个选项。

    这并不是您想要的答案,但Jonathan Oliver就如何避免在消息传递中使用分布式事务并保持事务完整性写了大量文章:


    不确定这是否对你有帮助,但是,嘿

    事实证明,MSMQ+SQL+DTC甚至没有提供我们需要的一致性保证。我们以前遇到过这样一个问题:在将消息排入队列的分布式事务提交到数据库之前,消息被处理,从而导致读取过期。这是使用ReadCommitted隔离来使用队列的副作用,因为:

  • 启动事务A
  • 更新A中的数据库表
  • 队列中的消息
  • 请求提交
  • 消息队列提交
  • 启动事务B
  • 阅读B中的信息

  • 使用ReadCommitted读取B中的数据库表如果您想手动执行此操作,下面是一种可靠的方法。它满足(1)和(2),甚至不需要(3)和(4)中允许的自由

  • 生产者(业务逻辑)启动事务A
  • 在一个或多个表中插入/更新任何内容
  • 将相应的消息插入PrivateMessageTable(域的一部分,如果愿意,则为非共享)。这就是将要分发的内容
  • 提交事务A.Producer现在已经简单可靠地执行了写入操作,包括插入消息或回滚所有内容
  • 专用分发器作业从PrivateMessageTable查询一批未处理的消息
  • Distributer启动事务B
  • 将未处理的消息标记为已处理,如果修改的行数不同于预期(两个实例同时运行?),则回滚
  • 将消息的公共表示插入到PublicMessageTable(以任何方式公开的表)中。为公共表示分配新的严格顺序ID。因为只有一个进程在执行这些插入,所以这是可以保证的。请注意,该表必须位于同一主机上,以避免出现2PC
  • 提交事务B。分发服务器现在使用严格的顺序ID将每条消息精确地分发到公共表一次
  • 消费者(可以有多个)查询PublicMessageTable中Id大于其自己的LastSeenId的下一批消息
  • 消费者开始交易C
  • 使用者将其自己的消息表示形式插入其自己的表ConsumerMessageTable(从而推进LastSeenId)。Insert ignore可帮助防止多个实例运行。请注意,此表可以位于完全不同的服务器中
  • 提交事务C。消费者现在只使用了每条消息一次,与消息公开的顺序相同,从未跳过消息
  • 我们可以根据消耗的信息做任何我们想做的事情
  • 当然,这需要非常仔细的实施

    它甚至适用于数据库集群,只要只有一个写节点,并且读和写都执行因果关系检查。也许有一个是足够的,但是我必须更仔细地考虑它的含义。