Orleans 2.0 官方文档 —— 4.8.2 Grains -> Grain持久化 -> 关系型存储

关系型存储

Orleans关系型存储的后端代码,建立在通用的ADO.NET功能之上,因此与数据库供应商无关。在前一章的运行时表格中,已经解释了Orleans数据存储布局。按照“ Orleans配置指南”和“ SQL表”中的说明,设置连接字符串。

要使Orleans代码在给定的关系数据库后端发挥作用,需要执行以下操作:

  1. 必须将恰当的ADO.NET库加载到进程中(GAC中可以存在多个库或其他库)。按常见的方式定义就好,例如,通过应用程序配置中的DbProviderFactories元素。
  2. 在定义连接字符串的元素中,通过AdoInvariant配置来ADO.NET不变量,默认情况下是System.Data.SqlClient。
  3. 数据库需要存在,并与代码兼容。这是通过运行供应商特定的数据库创建脚本来完成的。这些脚本位于OrleansSqlUtils NuGet包中,随每个Orleans版本一起发布。目前有两个数据库脚本:
  4. SQL Server - CreateOrleansTables_SqlServer.sql。AdoInvariant是System.Data.SqlClient
  5. MySQL - CreateOrleansTables_MySql.sql。AdoInvariant是MySql.Data.MySqlClient

如果您需要ADO.NET支持的其他数据库的安装脚本,请在Orleans Gitter上,提交一个问题或请求。

设计目标

1. 允许使用任何具有ADO.NET提供程序的后端

这应该涵盖了可用于.NET的最广泛的后端集,这是自有(on-premises)安装的一个因素。某些提供程序列在了ADO.NET Data Providers MSDN页面上,但为了备注方便,并未列出所有提供程序,例如Teradata。

2. 即使在一个部署正在运行时,也要保持适当地调整查询和数据库结构的潜力

在许多情况下,服务器和数据库由与客户有合同关系的第三方托管。这是常见的情况:承载环境是虚拟化的,性能会随着不可预见的因素而波动,例如承载环境下邻居的噪音或硬件的故障。Orleans二进制文件,甚至是应用程序二进制文件,都有可能无法更改和重新部署(合同关系的缘故),但通常可以调整数据库部署。改变标准组件,例如Orleans二进制文件,需要一个更为漫长的过程,来确定在给定情况下提供什么。

3. 允许使用特定于供应商和版本的功能

供应商已在其产品中实现了不同的扩展和功能。当这些功能可用时,使用它们是明智的。这些功能包括PostgreSQL中的本机UPSERT或PipelineDB, PolyBase或SQL Server中的本机编译表和存储过程 - 以及无数的其他功能。

4. 可以优化硬件资源

在设计应用程序时,通常可以预测哪些数据需要比其他数据更快地插入,哪些数据更有可能放入更便宜的冷存储(例如,在SSD和HDD之间拆分数据)。例如,进一步的考虑是,一些数据的物理位置可能更昂贵(例如SSD RAID比HDD RAID)、更安全或使用一些其他决策属性。与第3点相关,某些数据库提供特殊的分区方案,例如SQL Server 分区表和索引。

该原则也适用于整个应用程序生命周期。考虑到Orleans本身的一个原则是高可用性系统,应该可以在不中断Orleans部署的情况下调整存储系统,或者可以根据数据和其他应用参数调整查询。可参阅Brian Harry的博客文章,里面有一个变更的例子。

当一个表很小时,查询计划几乎无关紧要。当表是中等的时候,一个好的查询计划就可以了。当表是巨大的(数百万或数十亿行)时,查询计划中的一个微小的变化,就可能会杀了你。所以,我们对敏感查询会进行大量的提示。

一般而言,这是真的。

5. 不对组织中使用的工具、库或部署过程进行假设

许多组织都熟悉一组特定的数据库工具,例如Dacpac 或Red Gate。部署数据库可能需要权限或人员(例如DBA角色中的某个人)来执行此操作。通常这意味着,还需要有目标数据库的布局,和应用程序对数据库查询的草图,用来估计工作负载。可能存在一些流程,因受行业标准的影响,这些流程要求基于脚本的部署。在外部的脚本中拥有查询和数据库结构,可以实现这一点。

6. 使用接口功能所需的最小集合,来加载ADO.NET库和功能

这既快,又使得ADO.NET库实现的差异性更小。

7. 使设计可以共享

当它有意义时,例如在关系存储提供程序中,使设计易于共享。这意味着,没有依赖于数据库的数据(例如IDENTITY),并且它还基本上意味着,区分行数据的信息,应该仅建立在来自实际参数的数据的基础上。

8. 使设计易于测试

理想情况下,创建一个新的后端,应该与转换其中一个部署脚本,和向假设有默认参数的测试中添加新的连接字符串一样容易,检查是否安装了给定的数据库,然后针对它运行测试。

9. 考虑到前面的要点,为新后端制作移植脚本和修改已部署的后端脚本,要尽可能透明

实现目标

Orleans框架不了解特定于部署的硬件(在活动部署期间可能会更改)、部署生命周期中的数据更改以及某些在一定情况下才可用的供应商特定功能。出于这个原因,关系数据库和Orleans之间的接口应该遵循最小的抽象和规则集,既满足目标,也要使其能够有效地防止误用,并在需要时易于测试。参阅运行时表、集群管理和具体的成员协议实现。此外,SQL Server的实现包含了SQL Server版本特定的调整。数据库和Orleans之间的接口契约定义如下:

  1. 一般的想法是通过Orleans特定的查询读取和写入数据。Orleans在读取时对列名和类型进行操作,在写入时对参数名和类型进行操作。
  2. 实现必须保留输入和输出的名称和类型。Orleans使用这些参数,按名称和类型读取查询结果。只要维持接口契约,允许和鼓励特定于供应商和部署的优化。
  3. 跨供应商特定脚本的实现应该保留约束的名称。通过跨具体实现的统一命名,简化了故障排除。
  4. 版本 - 或应用程序代码中的ETag - 对于Orleans来说代表一个唯一的版本。只要它代表一个唯一的版本,它实际的实现类型并不重要。在实现中,Orleans代码不包含带符号的32位整数。
  5. 为了明确并消除歧义,Orleans期望一些查询返回TRUE作为> 0的值或FALSE作为等于0的值。也就是说,受影响的行或类似行并不重要。如果引发错误或抛出异常,则查询必须确保回滚整个事务,并且可以返回FALSE或传播异常。
  6. 目前,除了统计插入,其他的所有查询都是单行插入或更新(注意,如果关联的SELECT查询提供最后一次写入,则可以用INSERT查询替换UPDATE查询)。统计插入,如InsertOrleansStatisticsKey定义的那样,使用UNION ALL为除Oracle之外的所有数据库,以预先定义的最大大小,批量写入统计信息。而对于Oracle,则使用UNION ALL FROM DUALInsertOrleansStatisticsKey是唯一定义了一种模板参数的查询,Orleans的写入量,与具有不同值的参数的数量一样多。

数据库引擎支持数据库内编程,这类似于加载可执行脚本,并调用它来执行数据库操作的理念。在伪代码中,它可以被描述为

const int Param1 = 1;
const DateTime Param2 = DateTime.UtcNow;
const string queryFromOrleansQueryTableWithSomeKey = "SELECT column1, column2 FROM  where column1 = @param1 AND column2 = @param2;";
TExpected queryResult = SpecificQuery12InOrleans(query, Param1, Param2);

这些原则也包含在数据库脚本中。

应用自定义脚本的一些想法

  1. 使用IF ELSE 更改OrleansQuery中用于grain持久化的脚本,以便在某些grain使用(例如内存优化表)时,能使用默认的INSERT来保存某些状态。该SELECT查询需要作相应的调整。
  2. 在利用其他的特定于部署或供应商的方面时,可使用想法1.例如,在SSD或HDD之间拆分数据,将一些数据放在加密表上,或者通过SQL Server将统计数据插入Hadoop甚至链接服务器。

可以使用Orleans测试套件,或直接在数据库中使用 SQL Server单元测试项目,来测试更改后的脚本。

添加新的ADO.NET提供程序的准则

  1. 根据上面的“ 实现目标”部分,添加新的数据库设置脚本。
  2. 将供应商的ADO不变量名称,添加到AdoNetInvariants,将特定于ADO.NET提供程序的数据添加到DbConstantsStore。这些(可能)在某些查询操作中使用。例如,选择正确的统计插入模式(例如,带或不带FROM DUALUNION ALL)。
  3. Orleans对所有系统存储进行全面测试:成员,提醒器和各类统计。通过复制-粘贴现有的测试类,并更改ADO不变量名称,来完成为新数据库的脚本添加测试。此外,为了定义ADO不变量的测试功能,要继承RelationalStorageForTesting。
  •  

你可能感兴趣的:(Orleans)