使用 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 level serializable。但这会产生一大堆其他问题。 【参考方案1】:

我对这种锁定的方法是使用分布式锁,而不是锁定目标表本身。如果有的话,它将允许您在流程中包含更多逻辑。你不能使用标准的 c# lock 方法,因为你有同一个应用程序的多个实例需要共享同一个锁,所以你必须使用集中的东西。

我之前为此使用过 SQL Server 的 sp_getapplock - 您只需要一个可由应用程序的每个实例访问的单个 SQL 数据库。你可以手动调用这个 SP,或者我知道有一些 nuget 包可以将这个过程包装起来,使它更容易集成。但是您也可以选择使用 distributed locks in Redis 以及大多数其他缓存解决方案(如果您的解决方案中涉及其中任何一个)做同样的事情。

基本上,您可以对要防止同时运行的任何操作进行新的锁定。在您的情况下,它将避免同时运行对该表的多个更新。

话虽如此,您还可以考虑查看这些事件是如何引发和处理的,并看看您是否可以在该级别获得您正在寻找的弹性。就在我的脑海中,RabbitMQ(和其他消息队列)之类的东西允许在消息传递级别处理许多故障情况。我不知道这是否也值得研究(如果有的话,如果这些事件只需要处理一次,它可能会避免多次处理这些事件),但检查一下可能会有所帮助。

【讨论】:

以上是关于使用 sql server 实现服务冗余的主要内容,如果未能解决你的问题,请参考以下文章

在 SQL Server 中自动更新冗余/非规范化数据

Windows Server 2012R2 实现AD双域控制器互为冗余

Windows Server 2012R2 实现AD双域控制器互为冗余

sql server中如何实现在异地访问数据库

通过消除视图简化 SQL Server 查询

分享搭建域环境实现主域和文件服务器的热备冗余