Согласованность с etags и настройкой нескольких серверов?

Я пытаюсь понять, какая стратегия кэширования будет наилучшей в случае слоя REST API, который позволяет запрашивать и обновлять базу данных реестра клиентов. В настоящее время у нас есть 3 внешних сервера, все из которых общаются с центральным сервером базы данных.

Идея состоит в том, чтобы вернуть etag вызывающему клиенту с etag, совпадающим с идентификатором версии записи клиента (значение хеш-функции, которое обновляется при любом изменении в учетной записи) с вызовами обновления, принимаемыми только в том случае, если полученный etag соответствует идентификатору версии, хранящемуся на базу данных.

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

Если приходит второй клиент и выполняет тот же GET для той же записи о клиенте, направляемой на сервер 2, сервер 2 также кэширует запись локально и возвращает тот же заголовок etag.

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

После этого второй клиент выполняет условный вызов get, предоставляя набор заголовков If-None-Match с полученным тегом etag. Запрос снова попадет на сервер 2. Я предполагаю, что сервер 2 по-прежнему кэширует старый etag и возвращает клиенту ответ 304 Not Modified. Это правильное предположение?

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

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

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


person voda1983    schedule 12.11.2013    source источник


Ответы (3)


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

  1. Самый простой ответ заключается в том, что все интерфейсные серверы должны вызывать базу данных для проверки etag, прежде чем возвращать «304 Not Modified». Это может быть лучше, если есть много обновлений или стоимость загрузки записи из базы данных высока.

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

  3. Другой вариант заключается в том, что когда 1 внешний сервер видит обновление, он должен сообщить другим внешним серверам об истечении срока действия этого кэшированного элемента (возможно, вызвав веб-службу?). Это позволяет увеличить продолжительность кеша, но может быть слишком болтливым, если есть много обновлений.

person David    schedule 12.11.2013
comment
вы можете прокомментировать мой ответ. :)) - person Supun Wijerathne; 30.11.2017

+еще одно решение для списка @David:

  1. Используйте централизованный кеш. Это должно решить вашу проблему. Несмотря на то, что он менее эффективен, чем локальное кэширование, в большинстве случаев он все же быстрее, чем запрос к базе данных.

Возможные реализации кластерного кэша: couchbase, кластер redis. Наиболее популярной некластерной реализацией является memcached.

person Sergey Romanovsky    schedule 14.11.2013

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

Именование активов на основе их отпечатков пальцев (добавление) и создание некэшируемого верхнего слоя — вот основная идея.

person Supun Wijerathne    schedule 30.11.2017