Ловушки с локальным кэшем памяти недействительны с использованием RabbitMQ

У меня есть веб-сервер java, и в настоящее время я использую библиотеку Guava для обработки моего кэширования в памяти, которое я использую в большой степени. Теперь мне нужно расширить до нескольких серверов (2+) для переключения при сбое и балансировки нагрузки. В этом случае я переключился с кэша в процессе на Memcache (внешняя служба). Тем не менее, я не очень впечатлен результатами, так как сейчас почти для каждого звонка мне приходится делать внешний вызов на другом сервере, что значительно медленнее, чем кеш в памяти.

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

Кто-нибудь знает какие-либо потенциальные подводные камни такого подхода? Я немного нервничаю, потому что я не могу найти кого-либо еще, кто делает это в производстве. Единственные проблемы, которые я вижу, будут заключаться в том, что каждому серверу требуется больше памяти (в кэш-памяти), и для любого данного сервера может потребоваться немного больше времени для получения обновленных данных. Что-нибудь еще?

Ответ 1

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

У вас есть веб-приложение, которое использует кеш-память процесса для локальных данных. Вы хотите расширить до нескольких узлов и сохранить эту структуру для своей программы, а не полагаться на сторонний инструмент (memcached, Couchbase, Redis) со встроенной репликацией кеша. Итак, вы подумываете о том, чтобы скопировать свой собственный, используя RabbitMQ, чтобы публиковать изменения на разных узлах, чтобы они могли соответствующим образом обновлять локальный кеш.

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

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

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

Изменить

С учетом вашего заявления в комментариях, что вы видите время доступа в сотни миллисекунд, я собираюсь посоветовать вам сначала изучить вашу настройку. Типичные времена чтения для одного элемента в кеше из экземпляра Memcached (или Couchbase, или Redis и т.д.) Являются субмиллисекундными (где-то около 0,1 миллисекунды, если я правильно помню), поэтому ваш "проблемный ребенок" сервера кеша на несколько порядков, откуда он должен быть с точки зрения производительности. Начните там, а затем посмотрите, есть ли у вас такая же проблема.

Ответ 2

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

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