Архитектура для большого количества данных, обслуживаемых через HTTP API - PullRequest
2 голосов
/ 04 апреля 2011

Я создаю приложение для обслуживания больших объемов данных через REST API, и я ищу некоторые входные данные о том, как его архитектуру. Я использую .NET (C # 4.0), ASP.NET MVC и Sql Server 2008.

Сейчас у меня около 400 тыс. Строк в реляционной базе данных, и + - 5% из них обновляются в течение дня внутренним приложением, которое напрямую попадает в базу данных. Мне нужно передать эти данные через REST API, возвращая пользовательский формат XML. Однако данные должны быть обработаны, прежде чем я смогу их вывести. Хорошо, что я могу предварительно обработать его, если потребуется.

Я написал небольшой POC, который получает данные, обрабатывает их и кэширует в локальный XML-файл. Из-за обработки этот процесс занимает около часа, чтобы работать на всех 400 тыс. Строк. После завершения кэширования я просто возвращаю физический файл в каждом запросе.

Теперь мне нужно иметь возможность обновлять данные по мере их обновления в источнике и обновлять мой кэш, чтобы мне не нужно было генерировать все при каждом обновлении одной строки.

Я думаю об использовании AppFabric для хранения кеша памяти и использования физических файлов, просто чтобы убедиться, что в случае, если кеш памяти исчерпан, мне не нужно начинать с нуля. Как только строка обновляется в источнике, я обновляю кэш-память и записываю физический файл, чтобы убедиться, что он обновлен.

Таким образом, моим основным источником будет кэш AppFabric, затем файл физического кеша и, в крайнем случае, регенерация файла из базы данных, что займет около часа и сделает файл недоступным для того, кто его вызывает.

Я не очень доволен этим, но это то, что я получил. Есть предложения?

Большое спасибо!

Ответы [ 3 ]

1 голос
/ 11 апреля 2011

Думали ли вы об использовании Linq To Xml?

Вы будете лучше знать, подходит ли оно другим вашим ограничениям, но вот мои 2 пенса:

плюсы:

  • Xml - ваш целевой формат, поэтому нет проблем с конвертацией
  • это читабельно
  • очень прост в использовании (CRUD)
  • загрузка / сохранение в файл решит проблему «перезагрузки обработанных данных при перезапуске службы»
  • имеет достаточно эффективную реализацию, то есть может обрабатывать ваши 400 тыс. Строк (в зависимости от размера записи).
  • использование linq означает, что вы можете легко распараллелить его (с PLINQ), таким образом, эффективно используя свои ядра

минусы:

  • использование памяти может быть проблемой, но это зависит от размера вашей записи

Ниже (для элементов 500k) сгенерировано за 2 сек и обновлено все цены на элементы менее чем за 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");
1 голос
/ 12 апреля 2011

Спасибо за ваше разъяснение выше.Вот вариант, основанный на этом.

Добавить таблицу в вашу БД.Назовите это Products_Processed (или Price, как угодно).Эта новая таблица имеет одну строку для каждой строки в Продуктах (например, 1 к 1 с исходными данными).Каждая строка в этой новой таблице содержит обработанные данные для соответствующей строки источника.

Каждый раз, когда внешняя программа обновляет строку в Products, вы вычисляете только эту строку и обновляете соответствующую строку в Products_Processed.

Вот несколько способов заставить код работать только на недавно обновленных записях:

  • В вашей программе есть поток, который опрашивает БД раз в секунду (или минуту).Ваша логика обработки любых строк обновляется в последнюю секунду, начиная с одной секунды (или минуты) назад.Это означает, что вы сохраняете временную метку при обновлении строки «Продукт» (что, вероятно, в любом случае является хорошей идеей).
  • Если вы не хотите использовать временную метку, в базе данных таблицы «Продукты» есть триггер, который добавляетобновлены строки в таблице Products_ToProcess.Опросите его и запустите логику обработки для записей, которые там появляются, и удалите из Products_ToProcess
  • Используйте триггер для таблицы продуктов, который фактически вызывает ваш код C #: Создание и запуск CLR Триггер SQLServer

При таком подходе ваши производные данные логически близки к источнику правды (в БД с исходными данными) и сокращают количество копий / форматирования / обработки данных.Кроме того, важно то, что использование проверенных и обеспеченных DB механизмов для обнаружения / запуска измененных данных избавит вас от написания большого количества собственного кода синхронизации.

Теперь, возвращая ваши результаты, вы получите select * from Products_Processed.Если вы хотите вернуть обработанные данные только для определенных продуктов, у вас есть все возможности SQL и вашей схемы;аналогично для сортировки.Вся эта установка должна быть достаточно быстрой, чтобы вам не нужно было кэшировать файл на диске.На самом деле, кеширование MSSQL, вероятно, должно хранить большинство / все строки обработанных данных в ОЗУ, если у вас достаточно, поэтому вам редко придется делать холодный выбор (и, если у вас недостаточно ОЗУ, подумайте, какие несколькопо сравнению с вашим временем стоит потратить лишние концерты, бросая аппаратные средства в проблему, это никогда не обманывает;).

(Однако, если вы действительно хотите записать его на диск, вы можете сохранить смещения в физическом файле для каждой записи строки и быстро обновить отдельные данные в файле по мере обновления соответствующей строки обработанных данных.)

1 голос
/ 04 апреля 2011

Можете ли вы поместить всю обработку в базу данных? Если это правда, я думаю, что вы должны сохранить всю обработку там. 400 тыс. Строк - это небольшое количество строк, и SQLserver может справиться с этим нормально (час это слишком долго!). Попробуйте использовать службы интеграции для подготовки таблиц и выполните все операции вставки / обновления / выбора, используя «обработку набора» вместо обработки курсора / строки. Мои 2 цента.

...