【问题标题】:SQL Service Broker vs Custom QueueSQL Service Broker 与自定义队列
【发布时间】:2010-12-01 01:02:25
【问题描述】:

我正在创建一个群发邮件应用程序,其中一个 Web 应用程序设置了一个电子邮件模板,然后将一堆电子邮件地址排队等待发送。另一端将是一个 Windows 服务(或 exe),它将轮询此队列,获取要发送的消息。

我的问题是,与仅创建我自己的自定义队列表相比,使用 SQL Service Broker(或 MSMQ)有什么优势?

我正在阅读的所有内容都在建议我使用 Service Broker,但我真的看不出与平板相比有什么巨大优势(这对我来说使用起来会简单得多)。作为参考,该应用程序将用于几乎每天发送 50,000-100,000 封电子邮件。

【问题讨论】:

    标签: c# asp.net sql-server


    【解决方案1】:

    知道如何在平面表上实现队列吗?这不是一个愚蠢的问题,正确地在表上实现队列比听起来要困难得多。众所周知,类队列表容易出现死锁,您需要仔细考虑表设计以及入队和出队操作。另外,你知道如何扩展你的表池吗?你将如何处理重试和超时(即timers 的用途)?

    我并不是说您应该使用 SSB。学习曲线非常陡峭,主要是一个分布式应用平台,而不是本地排队产品,因此某些功能,如对话框,实际上对你来说是障碍而不是优势。我只是说您还必须考虑平面队列的困难。如果您从未实现过平面队列,请注意,那座桥下有很多龙。

    每天50k-100k 条消息 不算什么,每秒只有一条消息。如果您想要每 分钟 100k,那么我们有话要说。

    【讨论】:

    • 感谢您的回复。我知道无论我走哪条路,我都会有很多事情要处理。您是否有文章或示例应用程序可以让我指出正确的方向?无论我在哪里搜索,我都会不断收到更多问题,并且对自己在做什么越来越不确定。
    • 不幸的是我没有。过去,我曾在最可靠的来源(MVP 博客、sqlserverpedia、sqlmag 等)上搜索过此类文章,但找不到很好的总结文章。我从自己的经验中得到的一些建议:避开任何花哨的东西(比如优先级),试着让 FIFO 入队/出队正确(没有阻塞和无死锁)。还要确保将队列用于事件,而不是用于状态。 IE。将“发送此电子邮件的请求”排入队列,而不是电子邮件本身。
    • Rebus 或 NServiceBus 等服务总线具有 SqlTransport,它是表上队列的实现
    • @RemusRusanu 考虑到你的帖子Using tables as queues,你认为这个答案仍然有效吗
    • 我会更感兴趣地指出,如果您只想将 SSB 队列用作简单队列,您可以为每条消息重复使用相同的对话,而永远不要发出结束对话。它会找到工作,非常快,并且仍然集成到您的数据库中。 (内部/外部激活非常棒。)
    【解决方案2】:

    如果你每个人都需要移植到另一个供应商的数据库,如果你使用普通的表,你会遇到更少的问题。

    由于您的队列中似乎只有一个读取器和一个写入器,因此我倾向于使用标准表,直到您遇到问题。但是,如果您开始觉得需要使用“锁定提示”等,那么是时候切换到 Service Broker 队列了。

    如果发送方和读取方都需要数据库连接才能工作,我不会使用 MSMQ。如果发送方根本不与数据库通信,MSMQ 会很好,因为它允许发送方在数据库关闭时继续工作。但是,对于大多数系统而言,必须设置和维护 MSMQ 和数据库可能需要更多的工作。

    【讨论】:

    • 谢谢。我想我会(非常小心地)用一个平板来试用它,看看它的性能如何,因为这将是最快的实现。如果我发现它不符合标准,我将切换到 Service Broker。
    【解决方案3】:

    有关 Service Broker 的优势,请参阅此链接:

    http://msdn.microsoft.com/en-us/library/ms166063.aspx

    一般来说,我们会尝试使用工具或标准功能,而不是自己构建东西。这降低了成本,并且可以使升级更容易。

    【讨论】:

    • 谢谢,我已经阅读了那篇文章。我的问题是,就我而言,这些优势是否足以消除额外的学习曲线和复杂性。我的自定义表格非常简单,基本上可以归结为 3 个语句。伪代码:INSERT INTO Queue SELECT * FROM Queue WHERE Completed = false UPDATE Queue SET Completed = true
    • 如果没有服务代理,您必须注意线程。根据您的代码,如果在选择之后但在更新之前添加新行会发生什么。如果您的代码崩溃,电子邮件会被发送两次?
    【解决方案4】:

    我知道这是个老问题,但足够抽象,可以在足够长的时间内保持相关性。

    在使用这两种范式后,我建议使用平面表。它具有惊人的可扩展性和漂亮性。需要使用正确的提示。

    一旦应用程序开始分布式,或者开始在具有不同 RW 和 RO 服务器的组上使用多个,Service Broker(或任何其他分布式通信方法)就成为必需品。

    平桌

    • 只需要很少的提示(高度依赖于隔离级别)就可以在消费者(READPAST、UPDLOCK、ROWLOCK)中可扩展且可靠地工作
    • 消息处理的顺序并非一成不变
    • 如果处理失败,消费者必须确保消息留在队列中
    • 需要一些轮询机制(工作、CDC(这里是疯狂的地方:))、外部应用程序...)
    • 轮到表的维护作业和自动统计信息

    服务代理

    • 需要极度夸张的“基础设施”(消息类型、合同、服务、队列、激活程序,必须在每次服务器重启后启用,需要正确创建和删除对话......)
    • 非常不透明 - 在它神秘地停止工作后,我们花了很长时间试图让它运行
    • 有预定义的消息处理顺序
    • 如果 SB 被过度使用,它使用的表本身可能会导致死锁
    • 是唯一的方式(链接服务器除外...)直接从一个 HA 组的 RW 服务器上的数据库发送消息到该 HA 组中的 RO 数据库(无需任何外部应用程序)
    • 是在不同服务器之间发送消息的唯一方式(链接服务器是一个很大的 NONO(除非它们变成 YES - 你知道演习 - 这取决于))(无需任何外部应用程序)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-28
      • 2012-08-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多