Как отправить различия данных (возможно, JSON) на сервер?

Я собираюсь периодически отправлять набор текстовых данных с веб-страницы на сервер , возможно, в формате JSON.

При каждом нажатии могли не измениться никакие, некоторые или все данные. Чтобы уменьшить объем данных, которые я должен отправлять по сети, я хотел бы отправлять только разницу изменений при каждом нажатии.

Знаете ли вы какие-либо готовые решения / инструменты / библиотеки, которые:

  • Динамически создавайте различие JSON по мере внесения в него изменений (чтобы избежать сохранения oldJson и newJson и выполнения полного сравнения при каждом нажатии), написанного на JavaScript (т.е. для клиентской стороны)
  • Исправьте существующий фрагмент JSON с помощью JSON diff на стороне сервера, написанного на любой платформе, кроме Java или .NET ^ (необходимо запускать на Linux, Java не подходит для окружения, в котором я нахожусь, ни Mono ).

Более того, является ли это лучшим способом решения данной конкретной проблемы? Есть ли лучший способ перемещать фрагменты текстовых данных?

Изменить: некоторые пояснения:

  • Вероятная структура данных будет в основном довольно плоской (в том смысле, что она сильно связана, поэтому любые ссылки будут ссылками на основе идентификаторов, а не фактическими вложенными данными) совокупностью узлов. Узлы содержат набор деревьев, листья этих деревьев содержат фактические «примитивные» данные, такие как числа, строки и идентификаторы. Большинство изменений данных будет в листьях.
    • Большинство конечных данных будут очень маленькими (примитивы или меньше абзаца текста), но некоторые будут очень длинными (страницы с «богатым» текстом).
  • На данный момент мы можем рассматривать это строго один к одному, т. Е. Есть только один клиент, подключенный (в режиме чтения / записи) к любой конкретной структуре данных.
  • Было бы неплохо сделать сервер как можно более минимальным с точки зрения сложности - идея состоит в том, чтобы как можно больше отказаться от сервера. Хотя HTML5 все еще в основном не поддерживается, мне все еще нужен для хранения данных, хотя ...

^ То, что вы ожидаете от случайного виртуального хостинга. Я говорю о ваших хороших друзьях: PHP, Python, PERL, Ruby и т. Д. Или что-то, что можно легко установить на случайном общем хостинге.

Ответов (8)

Я тоже боролся с этим. Мне будет очень интересно, если кто-нибудь предложит лучший ответ, чем мой, но пока ...

во-первых, http://www.xn--schler-dya.net/blog/2008/01/15/diffing_json_objects/

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

Другой вариант - не пытаться решить проблему с помощью алгоритма DIFF. Это довольно неэффективно, и в зависимости от проблемы вы можете получить более высокие показатели производительности, просто отправив весь блок данных, даже если вы в конечном итоге будете повторяться. Это верно в основном для очень маленьких фрагментов данных. Очевидно, наступит поворотный момент, поскольку объем данных, которые вам необходимо передать, станет больше, но без каких-либо измерений будет неочевидно, где находится поворотный момент. Хитрость здесь в том, что чем больше становятся ваши данные, тем больше времени уходит на вычисление различий. Поворотный момент определяется только пересечением двух линий, образованных скоростью роста каждого метода, каждая из которых будет линейной или хуже, в зависимости от того, как реализована ваша разница. В худшем случае

Следующая остановка, прежде чем пытаться использовать diff, - заключить ваш доступ к данным в методы «get», «set» и «delete», которые отслеживают вносимые изменения. Данные, которые вы отправляете по сети, по сути, будут последовательным журналом использования этого метода, который вы сбрасываете со стороны клиента при каждой успешной передаче. На стороне сервера вы применяете этот журнал к данным на стороне сервера с аналогами на стороне сервера для ваших методов доступа к данным. Это несколько более легкое решение, чем diff, которое не требует такой большой вычислительной мощности.

Наконец, если вы собираетесь провести сравнение, наиболее эффективный способ, который я могу придумать, - это разбить свой набор данных на дискретные «блоки», каждый с уникальным идентификатором. Затем, когда вы запускаете различие, его ход будет точно на уровне "фрагментов". то есть единственное, что вы можете сравнить, - это ID с ID. Если вы измените чанк, присвойте ему новый идентификатор. Чем быстрее вы можете позволить себе разработать алгоритм сравнения, тем меньше времени потребуется на его выполнение.

В качестве альтернативы, вместо того, чтобы назначать новый идентификатор при изменении, вы можете просто запустить diff, чтобы проверить, "изменился ли" конкретный объект, остановиться, как только вы обнаружите изменение, и просто пометить этот фрагмент для повторной отправки в его entirity, чтобы обновить блок на стороне сервера с тем же идентификатором. Это можно было бы сделать еще более эффективным, если бы у вас был какой-то алгоритм быстрого хеширования для ваших фрагментов, который вы могли бы использовать для быстрого установления равенства.

Если последовательность ваших фрагментов не имеет значения, или если вы можете сохранить последовательность как свойство самих фрагментов, а не моделировать их физической последовательностью фрагментов, то вы даже можете создать ключи для фрагментов по идентификатору. Затем для обнаружения различий достаточно просто перечислить ключи объекта A и найти их на объекте B, а затем наоборот. Это намного проще реализовать, чем "настоящий" алгоритм сравнения, он имеет производительность O (a + b), что (я думаю) лучше, чем худший сценарий для реального алгоритма сравнения, который вы, вероятно, получите, если вы пытаетесь реализовать самостоятельно, иначе получите плохую реализацию.

зачем вообще создавать разницу, не было бы эффективнее подключаться к событиям, которые изменяют ваши данные, и генерировать измененный набор данных на основе этих изменений? Поскольку ваш код будет встроен в браузер, вы будете ограничены JavaScript, поэтому создание diff может убить производительность вашего приложения.

«Я создал метод для возврата структурных различий между двумя объектами JSON».

http://www.xn--schler-dya.net/blog/2008/01/15/diffing_json_objects/

Сегодня я публикую небольшой плагин jQuery, выполняющий различие между двумя объектами JS. http://plugins.jquery.com/project/jquery-diff

Я использую его в приложении для отправки на серверную часть только измененных данных.

Эта библиотека вычисляет полные различия JSON (включая различия строк): https://github.com/kbadk/json0-ot-diff

Формат diff основан на этом проекте https://github.com/ottypes/json0 , который предоставляет библиотеку, которая может «применять» различия к объектам.

Этот связанный проект обрабатывает применение различий OT к постоянным данным, а также транслирует различия нескольким клиентам для совместной работы в режиме реального времени: https://github.com/share/sharedb

Он не знает JSON, но есть метод, который Google, похоже, использует для Документов (их версия вышеупомянутой проблемы Etherpad).

http://code.google.com/p/google-diff-match-patch/

Он не был бы осведомлен о JSON, но он позволил бы вам сгенерировать эффективную клиентскую сторону diff в JavaScript и заставить сервер применять его с помощью соответствующей реализации (Java, JavaScript, C++, C#, Objective C, Lua или Python ).

Этот ответ на другой вопрос может быть полезен, особенно в части, касающейся модифицированной версии google-diff-match-patch: текстовое различие JSON

где-то здесь есть дипломная работа, чтобы найти решение, которое одновременно эффективно передает «что нового» и хорошо сочетается с веб-архитектурами (кэширование и сохранение минимального количества состояния на сервере).

Мне любопытно, что там? Я боролся с этим же вопросом, идея «куска» в ответе @Breton - это своего рода то, к чему я иду, но не знаю, как это сделать.

edit: подождите - я получил это задом наперед, я думал, вы говорите о сервере, вычисляющем различия для отправки клиенту.

Возможно, вы могли бы описать в расплывчатых деталях структуру данных на клиенте, которые отправляются на сервер. Я бы не стал делать это на основе самого текста JSON, если это вообще возможно; делать различия из Javascript. Если это список элементов с известной структурой, отслеживайте, какие из них вы отправили на сервер, а остальные отправьте. Если это более сложный набор данных, не знаю, как вам в этом помочь.

EtherPad решил нечто подобное, превратив каждое изменение источника в математическую операцию, которая могла быть коммутативной, ассоциативной и т. Д. Я бы счел это нетривиальной проблемой, и EtherPad смог сформировать бизнес вокруг решения этой проблемы.

edit: что интересно, это именно та проблема, которую решает хороший DVCS, такой как Git, но не в браузере.