gpt4 book ai didi

c# - 使用 SQL Server 数据事件进行消息传递

转载 作者:可可西里 更新时间:2023-11-01 08:43:02 25 4
gpt4 key购买 nike

在我们的组织中,我们有一个 SQL Server 2005 数据库和相当数量的数据库客户端:网站(php、zope、asp.net)、富客户端(legacy fox pro)。现在我们需要将核心数据库中的某些事件传递给其他系统(MongoDb、LDAP 等)。消息传递范式似乎非常有能力解决此类问题。所以我们决定使用 RabbitMQ broker 作为中间件。

从数据库中消费事件的问题起初似乎只有两种可能的解决方案:

  • 轮询数据库中的传出消息并将它们传递给消息代理。
  • 在某些表上使用触发器将消息传递到同一台机器上的代理。

  • 由于涉及定期执行 sql 时出现的延迟问题,我不喜欢第一个想法。

    但是基于事件的触发器方法有一个问题,目前对我来说似乎无法解决。考虑这个场景:
  • 将一行插入到表中。
  • 触发器触发并发送消息(使用 C# 编写的 CLR 存储过程)

  • 除非回滚写入数据的事务,否则一切正常。在这种情况下,数据将是一致的,但消息已经发送并且无法回滚,因为触发器在写入数据库日志时触发,而不是在事务提交时(这是 RDBMS 的正确行为) .

    我现在意识到我对触发器的要求太多了,它们不适合处理数据以外的任务。

    所以我的问题是:
  • 有没有人设法使用触发器提取数据事件?
  • 您可以建议哪些其他使用数据事件的方法?
  • 查询通知(建立在 Service Broker 之上)是否适合我的情况?

  • 提前致谢!

    最佳答案

    以免首先从等式中剔除明显的不合适:查询通知不是用于此的正确技术,因为旨在解决相对稳定数据的缓存失效问题。使用 QN,您只会知道该表发生了变化,但您将无法知道发生了什么变化。

    感谢您找出调用 SQLCRL 的触发器不起作用的原因:回滚时一致性被破坏。

    那么有什么作用呢?考虑一下:BizTalk Server .换句话说,围绕这个问题空间建立了一个完整的业务,解决方案远非微不足道(否则没有人会购买这样的产品)。

    尽管遵循一些原则,您可以走得很远:

  • 去耦 .基于事件的触发器是可以的,但不要从触发器发送消息。除了回滚时的一致性问题外,您还存在让每个 DML 操作现在等待外部 API 调用(RabbitMQ 发送)的延迟问题和外部 API 调用失败的可用性问题(如果 RabbitMQ 不可用,则您的数据库不可用) )。解决办法是让触发器使用普通tables as queues ,触发器将在本地数据库队列中排队一条消息(即将插入到此表中),并且外部进程将通过使消息出列(即从表中删除)并将它们转发到 RabbitMQ 来为该队列提供服务。这将事务与 RabbitMQ 操作解耦(外部进程只有在原始 xact 提交时才能看到消息),但代价是一些明显的附加延迟(涉及额外的跃点,本地表充当队列) .
  • 幂等性 .由于 RabbitMQ 无法在数据库中注册分布式事务,因此您无法保证 DB 操作(作为队列的本地表的出队)和 RabbitMQ 操作(发送)的原子性。当另一个失败时,任何一个都可以成功,并且在没有明确的分布式事务注册支持的情况下根本无法解决它。这意味着应用程序会每隔一段时间发送重复的消息(通常是当事情由于某种原因已经变坏时)。快速提醒一下:加入明确的“确认”消息并发送序列号的行为是一场失败的战斗,因为您很快就会发现您正在消息传递之上重新发明 TCP,这条路是由实体铺成的。
  • 公差 .出于与上述项目相同的原因,有时您认为已发送的消息将永远不会成功。同样,这造成的损害完全是特定于业务的。问题不在于如何防止这种情况(几乎不可能......),而是如何检测这种情况,以及如何处理。恐怕没有银弹。

  • 您确实提到了 Service Broker(支持查询通知的事实是它最不感兴趣的方面......)。作为 SQL Server 中内置的消息传递平台,它提供 Exactly Once In Order 交付保证并完全事务处理,它将解决上述所有痛点(您可以 SEND 来自触发器而不受惩罚,您可以使用 Activation 来解决延迟问题,你永远不会看到重复或丢失的消息,有明确的错误语义)和我之前没有提到的其他一些痛点(备份/恢复的一致性,因为数据和消息位于同一存储单元上 -数据库,HA/DR 故障转移的必要性,因为 SSB 支持数据库镜像和集群等)。但缺点是 SSB 只能与另一个 SSB 服务对话,换句话说,它只能用于在两个(或多个)SQL Server 实例之间交换消息。任何其他用途都需要各方使用 SQL Server 来交换消息。但是如果你的端点都是SQL Server,那么考虑一下还有一些 large scale deployments using Service Broker .请注意,像 php 或 asp.net 这样的端点可以被认为是 SQL Server 端点,它们只是数据库 API 之上的编程层,不同的端点需要从手持设备(手机)直接发送消息到数据库(而且 99% 的时间都是通过 Web 服务进行的,这意味着它们最终可以到达 SQL Server)。另一个考虑是 SSB 面向 throughput和可靠的交付,而不是低延迟。例如,绝对不是用于在 HTTP Web 请求中获取响应的技术。是用于提交处理由 Web 请求触发的内容的技术。

    关于c# - 使用 SQL Server 数据事件进行消息传递,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13087058/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com