通过HTTP API提供大量数据的体系结构

时间:2011-04-04 14:37:28

标签: api architecture reference dataset

我正在构建一个应用程序,通过REST API提供大量数据,我正在寻找有关如何构建它的一些输入。我正在使用.NET(C#4.0),ASP.NET MVC和Sql Server 2008。

现在我在一个关系数据库中有大约400k行,其中有5%的行是由直接进入数据库的内部应用程序在当天更新的。我需要通过REST API提供这些数据,返回自定义格式的XML。但是,在输出数据之前需要处理数据。好消息是,如果需要,我可以预先处理它。

我写了一个小POC来获取数据,处理数据并将其缓存到本地XML文件中。由于处理过程,此过程大约需要一个小时才能处理所有400k行。缓存完成后,我只需在每个请求中返回物理文件。

现在我需要能够在源中更新数据时更新数据并更新我的缓存,这样我就不需要在每一行更新时生成所有内容。

我正在考虑使用AppFabric来保留内存缓存并使用物理文件来确保在内存缓存耗尽的情况下我不需要从头开始。一旦在源中更新了一行,我就会更新缓存并写入物理文件以确保它是最新的。

所以我的主要来源是AppFabric缓存,然后是物理缓存文件,作为最后的手段,从数据库中重新生成大约需要一个小时的文件,并使文件无法被调用。

我对此并不满意,但这是我得到的。有什么建议吗?

非常感谢!

3 个答案:

答案 0 :(得分:1)

你能把所有处理都放在数据库中吗?如果是真的,我认为你应该保留所有处理。 400k行是少量的行,SQLserver可以处理这个问题(一小时太长了,不能这样做!)。尝试使用集成服务来登台表,并使用“set processing”而不是使用游标/行处理来执行所有插入/更新/选择。 我的2美分。

答案 1 :(得分:1)

您是否考虑过使用Linq To Xml?

你最了解它是否适​​合你的其他约束,但这是我的2便士:

专业人士:

  • Xml是您的目标格式,因此转换没有问题
  • 可读
  • 非常好用(CRUD)
  • 加载/保存到文件将解决“服务重启时重新加载已处理数据”问题
  • 具有相当高效的实现,这意味着它可以处理您的400k行(取决于您的记录大小)。
  • 使用linq意味着您可以轻松地将其与PLINQ并行化,从而有效地使用您的核心
缺点:

  • 内存使用可能有问题,但这取决于您的记录大小

以下(对于500k元素)在2secs中生成并在一个好的开发框中更新了0.5秒内的所有元素价格:

var root = new XElement("root");

for (int i = 0; i < 500000; i++)
{
    root.Add(new XElement("product", new XAttribute("name", "product_" + i),
                          new XElement("price", 13.0 + 1.0/(i + 1))));
}

foreach (XElement updateElem in root
    .Elements("product")
    .Where(x => x.Attribute("name").Value.StartsWith("product")))
{
    updateElem.Element("price").Value = "16.0";
}

root.Save(@"c:\temp\huge.xml");

答案 2 :(得分:1)

感谢您的澄清。这是一个基于此的选项。

向您的数据库添加一个表。称之为Products_Processed(或价格,无论如何)。这个新表对于Products中的每一行都有一行(例如,与源数据一对一)。此新表中的每一行都包含相应源行的已处理数据。

每次外部应用程序在Products中更新行时,您只计算该行并更新Products_Processed中的相应行。

以下是使用新更新的条目运行代码的几种方法:

  • 在程序中有一个线程,每隔一分钟(或一分钟)在最后一秒(或一分钟)之前更新的任何行上运行处理逻辑,轮询数据库。这意味着你要在产品行更新时保留一个时间戳(无论如何这可能是一个好主意)。
  • 如果您不想要时间戳,请在Products表的数据库中使用触发器,将更新的行添加到Products_ToProcess表中。轮询并对出现在那里的条目运行处理逻辑,然后从Products_ToProcess中删除
  • 在产品表上使用实际调用C#代码的触发器:Create and Run CLR SQLServer Trigger

此方法使您的派生数据在逻辑上接近真实源(在包含源数据的DB中),并减少复制/格式化/处理数据的次数。此外,重要的是,使用经过验证的DB提供的机制来检测/触发已更改的数据将使您无需编写大量自己的同步代码。

现在,返回结果主要是流出select * from Products_Processed。如果您只想返回特定产品的已处理数据,您可以充分利用SQL和架构;同样用于分类。整个设置应该足够快,您不需要将文件缓存在磁盘上。事实上,如果你有足够的MSSQL缓存应该可以保留RAM中的大部分/全部已处理数据行,所以你很少需要进行冷选(如果你没有足够的RAM,请考虑一下与你的时间相比,额外的演出是值得的;在问题上投掷硬件永远不会作弊;)。

(但是,如果您确实要将其写入磁盘,则可以将偏移存储到每个行记录的物理文件中,并在更新相应的已处理数据行时快速更新文件中的各个数据。)< / p>