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