2013-05-16 5 views
6

Хотите синхронизировать данные кэша между двумя серверами. Обе базы данных используют одну и ту же базу данных, но для более качественных данных выполнения я загрузил данные в Hash Map при запуске. Таким образом, вы хотите синхронизировать кешированные данные без перезапуска серверов. (Оба сервера запускаются одновременно).Лучший способ синхронизации данных кеша между двумя серверами

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

ответ

22

Вместо того, чтобы пытаться синхронизировать кешированные данные между двумя экземплярами сервера, почему бы не централизовать кеширование вместо использования чего-то вроде memcached/couchbase или redis? Использование распределенного кэширования с чем-то вроде ehcache намного сложнее и подверженность ошибкам IMO против централизации кэшированных данных с использованием кэширующего сервера, подобного упомянутому.

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

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

Если в данных действительно есть уровень волатильности (например, скажем, что вы кешировали искаженные данные сущности из БД, чтобы сохранить хиты в БД), то я все же считаю, что централизованное кэширование - это лучший подход, чем в -распространенное и синхронизированное кэширование. Вам просто нужно убедиться, что вы используете соответствующее время на кешированных данных, чтобы время от времени позволяло естественное обновление данных. Кроме того, вы можете просто удалить кешированные данные из централизованного хранилища, когда в пути обновления для определенного объекта, а затем просто перезагрузите его из кеша при следующем запросе этих данных. Это IMO лучше, чем пытаться сделать настоящий кеш-запись, где вы пишете в базовый магазин, а также в кеш. Сама БД может внести изменения в данные (например, по умолчанию используются недопустимые значения), и ваши кэшированные данные в этом случае могут не соответствовать тому, что находится в БД.

EDIT:

был задан вопрос в комментариях о преимуществах централизованного кэша (я предполагаю, что на что-то, как в памяти распределенного кэша). Я предоставлю свое мнение по этому поводу, но сначала стандартное заявление об отказе от ответственности. Централизованное кэширование - это не лекарство. Он предназначен для решения конкретных проблем, связанных с кэшированием в jvm-памяти. Прежде чем оценивать, следует ли переключаться на него, вы должны понять, что ваши проблемы в первую очередь, и посмотреть, соответствуют ли они преимуществам централизованного кэширования. Централизованное кэширование - это архитектурное изменение, и оно может быть связано с проблемами/оговорками. Не переключайтесь на это просто, потому что кто-то говорит, что это лучше, чем то, что вы делаете. Удостоверьтесь, что причина соответствует этой проблеме.

Хорошо, теперь, на мой взгляд, для каких проблем централизованное кэширование может решить vs in-jvm-memory (и, возможно, распределенное) кэширование. Я собираюсь перечислить две вещи, хотя я уверен, что есть еще несколько. Мои два больших: Общий объем памяти и Проблемы с синхронизацией данных.

Начнем с Общая площадь памяти. Скажем, вы выполняете стандартное кэширование объектов, чтобы защитить свою реляционную БД от чрезмерного стресса. Давайте также скажем, что у вас есть много данных для кэширования, чтобы действительно защитить вашу БД; говорят в диапазоне от многих ГБ.Если вы делаете кеширование в jvm-памяти, и вы говорите, что у вас 10 ящиков сервера приложений, вам нужно будет получить дополнительную память ($$$) раз 10 для каждого из ящиков, которые нужно будет выполнять кеширование в jvm Память. Кроме того, вам нужно будет выделить большую кучу для вашей JVM для размещения кэшированных данных. Я полагаю, что куча JVM должна быть небольшой и упрощенной, чтобы облегчить сбор мусора. Если у вас есть большие куски старого генерала, которые не могут быть собраны, то вы собираетесь подчеркнуть свой сборщик мусора, когда он войдет в полный GC, и попытается извлечь что-то из этого раздутого пространства старого поколения. Вы хотите избежать длительных периодов паузы GC2 и раздувания вашего старого генерала с этим не поможет. Кроме того, если требование к памяти превышает определенный порог, и вы использовали 32-битные машины для вашего уровня приложения, вам придется обновить до 64-битных машин, что может стать еще одной непомерно высокой стоимостью.

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

Теперь один быстрый пункт централизованного кэширования в целом. Вы должны настроить свое приложение таким образом, чтобы он мог выжить без кеша, если он полностью исчезнет в течение определенного периода времени. В традиционном кэшировании объектов это означает, что, когда кеш полностью недоступен, вы просто нажимаете свою БД непосредственно для каждого запроса. Не удивительно, но и не конец света.

Okay, теперь для Проблемы с синхронизацией с данными. При распределенном кэшировании в jvm-памяти вам нужно синхронизировать кеш. Изменение кэшированных данных в одном узле должно быть реплицировано на другие узлы и синхронизировано с их кэшированными данными. Этот подход немного страшен в том, что если по какой-либо причине (например, сбой сети) один из узлов выпадает из синхронизации, тогда, когда запрос отправляется на этот узел, данные, которые пользователь видит, не будут точными относительно того, что в настоящее время находится в DB. Хуже того, если они сделают другой запрос и попадут на другой узел, они будут видеть разные данные, и это будет запутать пользователя. Централизируя данные, вы устраняете эту проблему. Теперь можно было бы утверждать, что для централизованного кеша необходим контроль параллелизма вокруг обновлений для того же кэшированного ключа данных. Если два параллельных обновления входят в один ключ, как вы убедитесь, что два обновления не топают друг на друга? Моя мысль здесь состоит в том, чтобы не беспокоиться об этом; когда происходит обновление, отбросьте элемент из кеша (и сразу напишите в БД), и пусть он будет перезагружен при следующем чтении. Это безопаснее и проще. Если вы не хотите этого делать, вы можете использовать функциональность CAS (Check-And-Set) вместо оптимистического управления параллелизмом, если вы действительно хотите обновить как кеш, так и db для обновлений.

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

+0

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

+0

Обновлено ответом, чтобы включить некоторые преимущества ... – cmbaxter

+0

Thanx Cmbaxter ... Это действительно помогает ... –

8

Во-первых, постарайтесь забыть о преждевременной оптимизации. Вам действительно нужен кеш? 99%, что вам не нужно. В этом случае вы решили удалить избыточный код.

Если вам нужно, попробуйте прекратить изобретать колеса. Есть идеальные готовые библиотеки. Например, ehCache, который имеет распределенный режим.

+0

Спасибо за ответ. У меня около 5000 одновременных пользователей, поэтому я не могу удалить кеш, я полагаю. будет искать в ehCache ... –

2

HazelCast. Он позволяет синхронизировать данные между серверами с использованием протокола многоадресной рассылки. Он прост в использовании. Он поддерживает блокировку и другие функции.