Как отправить различия данных (возможно, JSON) на сервер? - PullRequest
19 голосов
/ 25 февраля 2009

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

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

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

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

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

Редактировать: Некоторые уточнения:

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

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

Ответы [ 8 ]

5 голосов
/ 25 февраля 2009

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

сначала, есть http://www.xn - schler-dya.net/blog/2008/01/15/diffing_json_objects/

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

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

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

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

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

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

4 голосов
/ 25 февраля 2009

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

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

2 голосов
/ 16 сентября 2010

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

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

1 голос
/ 22 августа 2011

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

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

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

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

1 голос
/ 25 февраля 2009

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

0 голосов
/ 22 апреля 2018

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

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

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

0 голосов
/ 24 февраля 2012

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

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

0 голосов
/ 25 февраля 2009

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

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

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

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

...