Определение места для запуска воспроизведения сообщений, когда некоторые сообщения могли быть потеряны из-за аварии.

У меня есть приложение-издатель, которое отправляет сообщения нескольким подписчикам. Каждому сообщению присваивается возрастающий порядковый номер. Допустим, A, B и C — три подписчика, и издатель отправил сообщение номер 1 пользователю A, номер 2,3,4,7 — номеру B и номер 5,6 — номеру C.

Будет ли сообщение с номером x отправлено подписчику A, B или C, является функцией некоторого неизменного атрибута сообщения (не числа), т. е. сообщение номер 7 направляется на B, поскольку оно может относиться к акции, символ которой начинается с «b». .

У издателя есть карта с максимальным порядковым номером, отправляемая каждому подписчику. Карта на данный момент будет выглядеть так:

{"A" -> 1, "B" ->7, "C" ->6}

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

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

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

Текущий алгоритм, который я использую, заключается в том, чтобы найти максимальную последовательность сообщений, которую получил каждый подписчик. Скажем, мы получаем что-то вроде:

{"A"->1, "B" ->7, "C" ->6}

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

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

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

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

Пожалуйста, предположим, что:

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

person Amol Regmi    schedule 14.01.2019    source источник
comment
Может я тут что-то не понимаю, но если у каждого подписчика есть отдельный канал, по которому он получает сообщения, то не должен ли каждый канал обрабатываться отдельно?   -  person Paul    schedule 14.01.2019
comment
Почему бы вам не сохранить номер последнего отправленного сообщения для каждого подписчика, поскольку в вашем случае подписчики кажутся независимыми (все они могут получать совершенно разные сообщения)? Или я что-то упускаю?   -  person Toady    schedule 14.01.2019
comment
Павел - Да, подписчики независимы. Предположим, что подписчик А видел сообщение номер 5, поэтому нам просто нужно выяснить из текущего состояния издателя, должен ли он отправить что-либо выше 5, а затем отправить только эти сообщения. Проблема здесь в том, что у издателя нет этих сообщений в кеше (он должен запросить их с другого внешнего FIX-сервера). Таким образом, идея здесь состоит в том, чтобы свести к минимуму то, сколько мы запрашиваем для воспроизведения. Извините, что не разъяснил это раньше.   -  person Amol Regmi    schedule 14.01.2019
comment
Почему бы вам не сохранить номер последнего отправленного сообщения для каждого подписчика, поскольку в вашем случае подписчики кажутся независимыми ----- да, они независимы, и действительно, я пытаюсь сохранить последнее отправленное сообщение для каждого подписчика, проблема заключается в том, чтобы определить с чего начать воспроизведение в этом состоянии. В основном предположим, что издатель был перезапущен внезапно, поэтому значение последних отправленных сообщений, сохраненных в постоянном хранилище, может быть устаревшим. Будет дорого обновлять это состояние для каждого отправленного сообщения.   -  person Amol Regmi    schedule 14.01.2019
comment
Хорошо, тогда у вас есть два случая: 1. подписчики полностью независимы, и в этом случае вы не можете свести к минимуму запросы, так как вам нужно будет запрашивать все разные сообщения; 2. подписчики не являются полностью независимыми, и в этом случае иногда необходимо повторно отправить одно сообщение нескольким подписчикам. В случае 2 вам нужно найти общие сообщения, чтобы возмущаться подписчикам, и хранить их до тех пор, пока они не перестанут быть полезными.   -  person Toady    schedule 14.01.2019


Ответы (1)


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

Все ли подписчики обновляют одну и ту же базу данных (или выполняют одно и то же действие) после получения обновления? В этом случае вы можете отправить последнее сообщение (7) одному из подписчиков.

Или каждый подписчик выполняет свое действие при получении сообщения? Затем вам нужно воспроизвести последнее сообщение каждого подписчика.{"A"->1, "B" ->7, "C" ->6}

person Vineeth Chitteti    schedule 14.01.2019
comment
Каждый подписчик будет обрабатывать сообщения одинаковым образом, но у нас есть логика разделения для принятия решения о том, куда должно отправляться сообщение, например, все сообщения, относящиеся к акциям, название которых начинается с буквы А, будут направляться подписчику «А». Мы можем определить, что сообщение 7 принадлежит подписчику B, но для этого нам нужно запросить повтор сообщения номер 7 с вышестоящего сервера. Я ищу способ свести к минимуму запросы на воспроизведение, я могу сделать некоторые специальные оптимизации, но подумал, что может быть шаблон или алгоритм для решения подобных проблем. - person Amol Regmi; 15.01.2019
comment
Я не думаю, что у вас есть другой вариант, кроме сохранения этих данных @AmolRegmi. Имейте одну запись для каждого подписчика или одну строку для всего списка подписчиков с указанием текущего сообщения, доставленного каждому подписчику (в зависимости от вашего варианта использования выберите один из вышеуказанных методов). И сохраняйте это сообщение после того, как вы получите сообщение 200, когда вы звоните подписчику. В случае перезапуска прочитать сообщение из БД и отправить все обновления от идентификатора сообщения в БД до последнего идентификатора сообщения. - person Vineeth Chitteti; 15.01.2019
comment
У меня есть сильное ощущение, что это архитектурная проблема, а не алгоритмическая. - person Vineeth Chitteti; 15.01.2019
comment
Вам нужно только найти последний идентификатор сообщения (или максимальное значение идентификатора среди идентификаторов сообщений), которое вы отправили в последний раз. И воспроизвести с этого идентификатора сообщения. Разве это не правда? Сохранять последний идентификатор сообщения в БД, который читается подписчиком. - person Vineeth Chitteti; 15.01.2019