SQL Server Service Broker 与 RabbitMQ

ara*_*ao6 6 sql-server service-broker

我们正在考虑使用 RabbitMQ 每分钟排队数千个任务,然后从 300 多个虚拟机处理它们。我们有一个智能调度 Web API,可以根据业务需求智能地(公平地)将 100 多个队列中的任务分配到 VM。我们知道 RabbitMQ 绝对有能力处理这种负载。目前,我们每次都跨多个表查询数据库,这占 SQL Server 负载的 30-40%。相反,我们正在考虑设置一个触发器,然后在数据进入时将数据推送到 RabbitMQ(通过中间交换 API)。我意识到 SQL Service Broker 与 RabbitMQ 相比也是一个潜在的队列选择,所以我有关于 SQL Service Broker(SQL Server 2016 及更高版本)的几个问题,希望您能回答:

  • 能否将队列数据持久化存储,然后根据业务需求从特定队列中获取任务?(我假设是的,但只是确认。)
  • 100 多个队列的可靠性如何?我记得旧版本的 Service Broker 非常不稳定。
  • 我们可以动态/以编程方式创建新队列吗?
  • 我们可以创建最小优先级队列吗(即当任务被推入队列时,它是根据优先级排序的)?
  • 对性能和负载有什么影响?至少使用 RabbitMQ,我们可以将队列管理责任卸载到 RabbitMQ 集群,让我们的 SQL Server 可以自由地处理其他查询。
  • 我们真的需要在队列之间设置某种“对话”才能使其工作吗?
  • 考虑一个与另一个,我们还需要注意其他任何差异/优点/缺点吗?

Dav*_*oft 9

能否将队列数据持久化存储,然后根据业务需求从特定队列中获取任务?(我假设是的,但只是确认。)

是的。

100 多个队列的可靠性如何?我记得旧版本的 Service Broker 非常不稳定。

队列就是一张桌子。SEND 是一个插入。RECEIVE 是一个删除。有一些功能可以从 SQL Server 内部处理队列,但您始终可以只使用外部客户端。

有关如何从外部应用程序处理队列的示例,请参见例如https://code.msdn.microsoft.com/Service-Broker-Message-e81c4316

我们可以动态/以编程方式创建新队列吗?

是的。但是就像动态创建表一样,它有不好的代码味道。

我们可以创建最小优先级队列吗(即当任务被推入队列时,它是根据优先级排序的)?

是的。

https://docs.microsoft.com/en-us/sql/t-sql/statements/create-broker-priority-transact-sql

对性能和负载有什么影响?

SEND 是对具有单个非聚集索引的聚集索引表的单行插入。RECEIVE 是删除一行。

我们真的需要在队列之间设置某种“对话”才能使其工作吗?

每个 SEND 和 RECEIVE 都处于“对话”的上下文中,这是两个“服务”之间潜在的长期会话。对话可以永远存在并可以重用,并且是开始使用服务代理时很多困惑的根源。

考虑一个与另一个,我们还需要注意其他任何差异/优点/缺点吗?

Service Broker 非常复杂,因为所有消息都是通过潜在的长期双工对话发送的,您必须在 TSQL 中针对它进行编程。一旦你理解了设计,很多 TSQL 的奇怪故障排除都是样板文件。

Service Broker 最好的一点是它不是一个单独的存储库,您的消息与其他数据具有相同的 HA/DR 和备份。在涉及其他应用程序数据的事务中登记 SEND 或 RECEIVE 是微不足道的。

如果您不想要数据库内消息传递,请考虑使用Azure 服务总线更简单、功能更多、在云中为您操作,并且能够轻松且廉价地处理该级别的规模。

同样对于许多场景,您可以只使用一个简单的表作为队列。参见例如来自 Remus Rusanu 的http://rusanu.com/2010/03/26/using-tables-as-queues/,他曾经是拥有 Service Broker 的 SQL 产品团队的一名 SQL。您不会遇到阻塞读取,但如果您的延迟要求可以容忍轮询循环中的读取器,那么它可能是一个不错的选择。


小智 7

我想我会增加 2 美分,因为我一直在使用 SSB 和 RabbitMQ (RMQ)。

首先:我同意大卫在他的帖子中所说的大部分内容。我唯一可能不同意“一点点”的是:

"Once you grok the design, and the strange troubleshooting a lot of the TSQL 
 is boilerplate." 
Run Code Online (Sandbox Code Playgroud)

在我的工作场所,我们非常广泛地使用 SSB,我们有很多流程在使用它。我们在 SQL Server 2005 仍处于测试阶段时开始使用 SSB(所以现在已经有好几年了),但我们仍然时不时地被 SSB 的“黑匣子”行为“咬住”。

所以,最近几年 - 对于新项目 - 我们已经开始使用 RMQ。我们所有的数据处理都发生在存储过程中,因此很容易在过程中创建“挂钩点”,并在该“挂钩点”中通过 SQLCLR 程序集将数据发送到 RMQ。您可以在此处阅读更多相关信息。SQLCLR 解决方案工作得非常好,我们每秒发送数千条消息(我们的数据库是 OLTP 24/7,具有非常高的吞吐量)。

无论如何,在我看来,SSB 和 RMQ 之间的选择归结为几件事(我假设数据源在数据库中):

  • 出队后数据的处理在哪里进行;在数据库中还是在外部进程中?如果是外部流程,我会倾向于 RMQ。如果处理发生在另一个数据库中,我会将 SSB 视为解决方案。但是,由于它的特性,我可能会考虑创建一个发布-订阅 SQLCLR 程序集。该程序集将异步读取表中的数据,并将其发送到另一个数据库进行处理(我们在我工作的地方也这样做过)。
  • 您需要 SSB 为您提供的双工功能吗?不要忘记 SSB 并不是完全打算成为消息代理,而是为(如大卫所说)双工对话而构建的,这可能是长期存在的。如果您需要双工功能,那么 SSB(几乎)是给定的。

希望这可以帮助!请让我们知道您的决定。