服务经纪人-对话寿命?


9

我们正在努力使Service Broker在我们的环境中工作,以解决业务案例。我不知道消息标题是否是一个好标题,但是我的问题在下面。但这可能不是一个好问题,所以在那之后我们要做的就是为什么我认为这是正确的问题。

在结束对话之前,应在对话中发送多少条消息?

我们要使用Service Broker来异步更新结果表。结果表平坦且快速。我们在基表上具有触发器,该触发器发送带有其表和主键的消息。我们有三个队列:

  • 低延迟-目标是处理15秒。它处理与特定项目有关的更改项目。
  • 批量队列-目标是5分钟的处理时间。它处理何时会影响数百(或数千)个项目的更改。它列出了受影响的项目列表,并将其馈入“延迟的低延迟队列”
  • 延迟的低延迟-目标是30分钟才能处理。这仅处理批量队列中的项目。

基本上,如果客户的信息更新;这会影响许多产品,因此将其发送到批量队列以减慢处理速度。但是,如果产品得到更新,则将其发送到低延迟队列。

我们重用类似于Remus Rusanu的博客http://rusanu.com/2007/04/25/reusing-conversations/的对话,不同之处在于我们是基于主键的模数来进行对话的。这具有辅助主键重复数据删除的附带好处。

因此,我们正在重新使用对话并且在我们的准则之内。通过两个线程,我能够每秒刻录125条消息(人为丢弃几千条消息),这远远超过了保持生产的速度(每秒15条消息)。

但是,我们遇到的问题是,经过一段时间,大约4个小时或120K消息,我们开始在sysdesend和队列表上看到块和高争用。锁是LCK_M_U,是KEY锁。有时,宏块解析为sysdesend,有时解析为特定的队列表(queue_)。

我们已经制定了一个流程,该流程将在闲置24小时或30分钟后结束对话,因此我们可以增加循环讨论之前的时间。

我们正在使用SQL 2016 Enterprise(13.0.4001.0)

  1. 触发触发(发送低延迟或批量发送)
  2. 查找或创建对话句柄。
  3. 发信息
  4. 队列激活过程
  5. 更新结果表

清理过程每10分钟运行一次,以查看是否有空闲的对话。如果连续超过三遍发现它们,则将其标记为无效并结束对话。

请让我知道是否还有其他可能有益的细节。我在Service Broker方面没有太多经验,所以我不知道我们的消息/秒是低,高还是无动于衷。

更新

因此,我们今天再次尝试,并遇到了相同的问题。我们将对话寿命更改为2小时,但没有任何效果。因此,我们实施了150招;有同样的问题。

大量等待SEND CONVERSATION,等待sysdesend。有人还有其他想法吗?

更新2

今天我们进行了更长的测试,并且在17分钟的采样期间之一中,我们在4个会话句柄上处理了41K条消息。当sysdesend上的锁和队列表变得过多,并且在停止它之前我们开始向后漂移时,我们能够保持到最后。我们似乎在处理消息方面没有问题,没有任何东西进入队列,我们​​可以将其拉出并以至少5倍的速度处理它们。基于添加消息,我们的速度似乎受到限制。

在以后的测试中,我们删除了占消息总数80%的触发器之一。即使负载大大减少,我们也开始看到相同的等待。

更新3

谢谢Remus的建议(也感谢您发布有关该主题的出色博客文章,它们对于达到这一点很有帮助)。

我们今天再次运行它,并且表现更好(因为在等待之前,我们走了更长的时间,甚至在我们瘫痪之前走了更长的时间)。所以,细节。

我们更改了:*将每个线程的可维护会话数从1:1增加到2:1。基本上,我们有4个线程的8个会话句柄。

  • 合并大容量队列(因为一条传入消息可能意味着数百条传出消息),从而合并为更少,更大的消息。

关于此尝试的注意事项:

  • 禁用目标队列激活过程。阻塞没有变化(我们等待了5分钟),消息确实发送到了sys.transmission_queues。

  • 监视sys.conversation_endpoints。这个数字从0很快就达到了13K,然后全天缓慢上升,直到大约5小时后才达到25K。直到达到16K +/-才开始阻塞

  • 我进入DAC并为队列运行DBREINDEX命令,尽管通过查询,幻象记录在进行清理并将计数降至0之前从未超过200左右。

  • 当我结束测试时,sysdesend和sysdercv的计数相同,为24,932。

  • 我们在5个小时内处理了约310K条消息。

我们走了很长时间,事情才崩溃了,我真的以为这次可以做到。明天我们将尝试强制消息通过网络。


1
we started seeing blocks and high contention on sysdesend and the queue table.->什么是等待类型- PAGELATCH_EX/SH and WRITELOG?您使用过150技巧吗?如果您要争用系统表,那么150技巧将非常有用。
金沙(Kin Shah)

@kin,我更新了问题,但是锁定类型为LCK_M_U或LCK_M_X。我已经阅读了150个技巧,但是希望在2016年没有必要(因为他们也解决了tempdb泄漏问题),而且还因为它看起来像是一种黑客。我们将再次投入生产(不幸的是,我们只会在生产工作负载中遇到此问题),并将首先尝试缩短生命周期。我将在这里更新结果。接下来是您引用的150个技巧。
乔纳森·菲特

我在Twitter上曾问过@RemusRusanu-他是服务经纪人的专家:-)
Kin Shah

这不是我以前见过的(长时间运行后SEND下降)。1)请告诉我sys.conversation_endpoints测试期间的行数是多少(恒定或正在增加,发生阻塞时的行数是多少)。2)发生阻塞时,禁用目标队列是否会影响SEND阻塞(禁用队列应将SEND路由到sys.transmission_queue)。和3)从长远来看,甚至迫使消息(甚至在本地)(设置SSB端点,添加路由)都可以改变行为
Remus Rusanu

还有一些想法:4)发生阻塞时,在目标上停止RECEIVE是否会有所作为(禁用已激活的proc,如果有的话)和5)目标队列中有多少个幻影记录?ALTER QUEUE ... REBUILD封锁开始后,跑步会有所作为吗?
雷木斯·鲁萨努

Answers:


3

我知道回答您自己的问题是一种不好的形式,但是我想对有兴趣的人关闭此表格。我们最终确实设法解决了该问题,或者至少解决了足以满足我们要求的问题。我要感谢所有发表评论的人。Remus Rusanu和Kin很有帮助。

我们的数据库非常繁忙,处于RCSI模式。我们有数以千计的移动设备每45秒更新一次其位置信息。通过这些更新,多个表将更新其信息(可怜的设计,因为我将易失性信息限制为单个表,然后将其加入以获得结果)。这些表与我们试图异步生成报告信息而不是让最终用户直接针对基本表的表相同。

最初,我们使触发器在每个update / insert语句中(在大多数情况下应该是一行)在修改后的记录上进行游标,然后将消息中的每个主键发送给服务代理。在服务代理内部,尤其是批量队列中,还有其他游标,它们执行报告的upsert过程(每个主键执行一次)。

最终使我们工作的是什么:

  • 我们删除了游标,并决定发送更大的消息。每个表的每个用户事务仍然有一条消息,但是现在我们发送的消息具有多个主键。

  • 大容量处理器还为每个消息发送多个密钥,从而减少了在将消息适当地改组到另一个队列时正在进行的SEND CONVERSATIONS的数量。

  • 最易失的表(我们的移动设备数据表)已删除了触发器。我们更新了upsert过程,以包括适当的外键,现在,当将结果提取给用户时,我们只是重新加入该表。该表轻松贡献了我们一天必须处理的消息的80%。

我们每天要处理大约1百万条消息(不包含“移动设备”表格),而我们的绝大多数消息(超过99%)都是在目标范围内处理的。我们仍然偶尔会有离群值,但鉴于其罕见的性质,它被认为是可以接受的。

影响因素:

  • 我在前面提到的对话清除过程中发现了一个错误,该错误实际上并没有适当地清除对话并过早结束对话。现在,这导致我们的sysdesend计数从不超过几千(大部分来自使用150技巧)。

  • 触发器中的游标似乎持有比预期更多的锁定(即使使用static,forward_only)。删除这些似乎使我们在SEND CONVERSATION上看到的锁本质上更加短暂(或至少我们看到的时间更短)。

  • 实际上,我们并排运行了两个解决方案(Service Broker解决方案后端(用于在生产负载下进行测试))和当前解决方案(跨多个表的可怕查询)。

作为附带的好处,这已经发现了Ghost Record Cleanup问题,尽管它不在Service Broker表(系统或队列)上,但在我们的系统中非常普遍,并且症状与我们的“不清楚的原因”非常吻合我们有时遇到的问题。对此的调查正在进行中,我们正在尝试查找有助于此结果的表,并且我们可能仅会定期重建其索引。

再一次谢谢你。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.