使用 sql server 实现服务冗余
Posted
技术标签:
【中文标题】使用 sql server 实现服务冗余【英文标题】:Service redundancy with sql server 【发布时间】:2020-07-17 08:08:34 【问题描述】:我有 2 个相同服务的实例在不同的机器上运行。这是为了确保高可用性(如果一台机器宕机,杀死第一个服务,那么第二个仍然可用)。
当触发总线事件时,这两个服务会同时更新和删除 SQL Server 表中的相同行。所以,我通常会在总线事件引发时得到一个 LinqToSql ChangeConflictException
。
为了处理这个问题,我目前用try catch
包围SubmitChanges
并且在ChangeConflictException
的情况下什么都不做。
有没有更干净的方法?
是否可以使用 Linq to SQL 锁定整个表? (以便其中一项服务在尝试更新之前等待锁被释放)。
【问题讨论】:
创建一个单独的表。把桌子锁在上面。运行您的原始代码。释放表锁。 如何使用 linqtosql 锁定表? ***.com/questions/25273157/… 谢谢;这很有趣。然而这是 t-sql,而不是直接使用 linqtosql。我试图避免这种情况(以及存储过程) 如果您要锁定表,也可以使用isolation levelserializable
。但这会产生一大堆其他问题。
【参考方案1】:
我对这种锁定的方法是使用分布式锁,而不是锁定目标表本身。如果有的话,它将允许您在流程中包含更多逻辑。你不能使用标准的 c# lock 方法,因为你有同一个应用程序的多个实例需要共享同一个锁,所以你必须使用集中的东西。
我之前为此使用过 SQL Server 的 sp_getapplock - 您只需要一个可由应用程序的每个实例访问的单个 SQL 数据库。你可以手动调用这个 SP,或者我知道有一些 nuget 包可以将这个过程包装起来,使它更容易集成。但是您也可以选择使用 distributed locks in Redis 以及大多数其他缓存解决方案(如果您的解决方案中涉及其中任何一个)做同样的事情。
基本上,您可以对要防止同时运行的任何操作进行新的锁定。在您的情况下,它将避免同时运行对该表的多个更新。
话虽如此,您还可以考虑查看这些事件是如何引发和处理的,并看看您是否可以在该级别获得您正在寻找的弹性。就在我的脑海中,RabbitMQ(和其他消息队列)之类的东西允许在消息传递级别处理许多故障情况。我不知道这是否也值得研究(如果有的话,如果这些事件只需要处理一次,它可能会避免多次处理这些事件),但检查一下可能会有所帮助。
【讨论】:
以上是关于使用 sql server 实现服务冗余的主要内容,如果未能解决你的问题,请参考以下文章
Windows Server 2012R2 实现AD双域控制器互为冗余