Как обрабатывать асинхронные вставки/обновления баз данных

#database #asynchronous

Вопрос:

допустим, у меня есть веб-приложение, которое выбирает пользователя через REST:

 GET /users/me
 
 {
  "id": 1,
  "name": "John Doe",
  "email": "john.doe@email.com"
}
 

Веб-приложение имеет возможность обновлять этого пользователя в форме, например, изменять name .
Обычно это реализуется с помощью конечной точки REST, которая записывает изменения в базу данных ( UPDATE users SET name = 'My new name' where id = 1 ) и возвращает результат в браузер.

Бизнес требует, чтобы эта система масштабировалась до миллионов одновременных пользователей, и одна из попыток сделать это-сделать эти типы запросов асинхронными. Изменение name не должно быть действием, которое требует немедленного реагирования. Его можно поместить в очередь и записать в базу данных, когда будут доступны ресурсы. Пользовательский интерфейс может отразить это, сделав запрос, а затем предположив, что данные были/будут обновлены. Но если пользователь перезагрузит страницу, возможно, будут извлечены старые данные (потому что изменение еще не было записано). Затем нам нужно будет реализовать хранилище в браузере, чтобы гарантировать name сохранение новых данных, и когда «новые» данные будут извлечены при перезагрузке, сравните что-то вроде a timestamp , чтобы узнать, какое значение является последним.

Что мне интересно, так это от кого — то, у кого есть опыт в этом-это распространенный способ сделать это? На какие потенциальные подводные камни нам следует обратить внимание? Какова была бы альтернатива?

Ответ №1:

Распространенный способ сделать это-вернуть что-то вроде идентификатора процесса, который клиент может использовать для проверки обработки запроса. Таким образом, конечная точка ‘changeUserName’ вернет идентификатор процесса, а конечная точка ‘checkProcessStatus’ вернет статус запроса, поставленного в очередь.

В интерфейсе вы можете показать, что изменение находится в ожидании, и время от времени опрашивать, чтобы проверить, изменился ли статус. Таким образом, на стороне клиента вы можете сохранить новое имя и идентификатор процесса. Когда статус процесса меняется на «успешно», все в порядке, когда он завершается неудачей, вы всегда можете запросить старое имя и уведомить пользователя о том, что что-то пошло не так.

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

Правка: немного больше о том, как это может работать. Вы создаете очередь для хранения действий/вещей для обработки, например » обновить имя пользователя до действия [новое имя]». Эта запись в очереди имеет статус и идентификатор процесса, а также, возможно, дополнительную информацию. «checkProcessStatus» просто вернет статус записи, что очень дешево и вернет только что-то вроде «ожидание» и, возможно, отметку времени. В фоновом режиме очередь обрабатывается, и статус обновляется до успешного, неудачного или любого другого. Вы также можете предоставить дополнительную информацию, такую как сообщения об ошибках или обновленные значения. В следующий раз, когда клиент использует «checkProcessStatus», он увидит новый статус.

Комментарии:

1. Спасибо тебе за ответ, Томас. Последующий вопрос. Разве конечная точка «checkProcessStatus» не должна знать старое значение и новое значение и запрашивать то, что сохраняется в базе данных, чтобы узнать, было ли оно обработано? Или ему нужно будет заглянуть в очередь (скажем, rabbitmq). Похоже, это дорогостоящая операция. Кроме того, относительно вашего последнего комментария: есть ли какой-либо конкретный «более простой» способ «масштабирования», о котором вы думаете?

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