我面临以下情况:
我正在研究的系统有几个不同的部分(服务和ASP.net),分别负责。这些部分由2个资源组合而成:MSSQL-DB和Windows文件系统上的文件。
目前,所有这些部件都单独访问这些资源。我认为这会造成不可预测性和不一致性。
我正在考虑引入一项规范对这些资源的访问的服务。我不确定这是否是一个公认的设计原则。
一般问题是:
我应该考虑什么样的解决方案,在设计时应该记住什么?
具体问题:
这只是一个数据访问层吗?
引入像这样的SPOF是不是很糟糕?
您能推荐针对此类解决方案的阅读材料吗? (特别是如果C#有特定材料的话)
由于allen-smithee的一个很好的问题而编辑:
数据库当前由嵌入式查询访问。它们被分成一个类,但每个服务都有所不同,因此它不是共享库。
答案 0 :(得分:1)
1 / A数据访问层简单地封装了数据逻辑,您需要的是concurrency control,以确保您的数据模型在独立服务中的一致性。
2 /根据你实现并发的方式,它可能是单点故障,但我认为没有任何问题 - “失败计划”是一个伟大的设计口号。您可以构建冗余和故障转移机制,也可以在服务中分发并发控制。
3 /您选择实现并发的方式取决于您的应用程序的功能以及用户期望的内容。举几个具体情景:
当服务开始更新时,启动事务并为所涉及的记录取出一个或多个行级锁。如果任何其他服务尝试同时编辑记录,则阻止或返回错误,例如“此记录当前已被锁定”。请注意,所有锁必须在读取之前进行,并在更新期间保留,以确保与其他写入保持一致。
优点 - 相当直接实施小型数据模型。 MSSQL支持大量锁定方案,甚至可以用来对资源进行分组的自定义application locks。
缺点 - 如果您的事务需要访问多个表/行,并且不同的服务或函数访问重叠表,您可以轻松地解决各种死锁问题。 MSSQL通常更喜欢悲观锁定,并且可以将锁从行升级到页面和表级别,这意味着读取和写入锁定可能会以您最初不期望的方式运行。您可能需要花费大量时间在SQL Server Profiler中调试这些交互,并准备好对数据模型进行更改以解决这些问题。
每个表行都有一个增量版本号。服务读取所需的数据,执行一系列更新,然后在事务锁中检查当前行版本与用于更新的行版本。如果版本号不匹配,则回滚事务,取消更新。然后,服务可以尝试从读取数据开始再次执行操作。
优点 - 当服务尝试提交更新时,不会阻止读取器并且仅保持锁定非常短暂。 MSSQL以“行版本控制”的形式内置了对此并发方法的支持,具有“快照隔离”级别。如果冲突很少,这种方法可以非常灵敏 - 非常适合实时应用。
缺点 - 此方法可能需要对数据模型和服务行为进行重大更改。
单个数据服务负责所有数据访问。其他服务从此服务请求数据并提交更新。该服务负责读取和写入数据库和文件系统,并执行某种程度的数据完整性检查并解决数据冲突。
优点 - 在一个模块中封装数据完整性和控制,简化其他服务。允许您在应用程序级别实现缓存,锁定等,从而提供更精细的控制。
缺点 - 需要对现有架构进行重大更改。如果您选择在字段级别解析,则解决数据冲突可能需要大量代码。当无法解决问题时,服务需要能够处理被拒绝的更新。
这是我能想到的主要场景,但还有更多。通常,对数据的所有并发控制都将围绕执行动作时的锁定(悲观锁定);执行操作然后检查冲突(通过版本控制进行乐观锁定);或执行一项行动然后合并冲突(冲突解决。)
考虑您的特定数据模型以及模型的更新方式将指导您将使用这些技术的哪种组合。搜索上述任何术语将为您提供大量阅读内容,并且有很多Technet文章专门针对MSSQL上下文中的这些问题。请记住 - 我看到优秀的程序员弄错了这个东西,这确实是一个具有挑战性的问题,但是如果你有条不紊地完成它,它是可以解决的。