2016-08-31 8 views
0

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

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

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

Любые идеи?

Спасибо.

EDIT

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

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

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

+0

Зачем вам нужно делать 'clear()', вы уверены, что ни одна из данных в кэше никогда не запрашивается снова? Что происходит с приложением и его производительностью за это время? Можете ли вы подробно рассказать о том, что внутренние объекты репозитория действительно имеют отношение к осколке? – cruftex

+0

Я только что отредактировал вопрос, чтобы добавить дополнительную информацию. Надеюсь, это ответит на ваши вопросы. – Kilian

ответ

0

Действительно, вы не хотите, чтобы был выставлен метод clear().

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

Теперь вы можете позволить менеджеру кластера использовать API репозитория и добавить код для вызова всей необходимой операции при изменении топологии. Но для менеджера кластера существует только зависимость от реализации репозитория, а не наоборот. Диспетчер кластеров не должен знать репозиторий, чтобы предоставлять его услуги другим клиентам.

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

Примечание стороны:

Есть продукты доступны, которые уже делают именно такой вид операций, например, Apache Ignite, Hazelcast, Infinispan.

+0

Мы фактически используем Ignite в качестве поставщика уведомлений о кластере. Очереди и темы, которые мы используем, - это реализации Ignite, и у нас есть подписки, созданные для любого изменения топологии. Но то, что у нас есть, - это то, что вы говорите, подписчик на это изменяется, а затем вызывает репозиторий (или кеш напрямую), чтобы очистить кеш. Насколько я понимаю, вы предполагаете, что сам репо подписывается на уведомления кластера. Должно ли репо заботиться о подписке на эти события? Я думал, что это не должно заботиться о чем-то, что не связано с настойчивостью. – Kilian

+0

Ну, если это так, тогда он также не должен кэшировать. И его из-за кеша нужны эти события. OTOH, посмотрите на компоненты, которые у вас есть, жизненный цикл и какие компоненты взаимодействуют друг с другом. Если есть два компонента, имеющих один и тот же жизненный цикл и разговаривающие только друг с другом, то его сильный индикатор принадлежит ему;) – cruftex

+0

Спасибо за комментарии и извините за задержку. Мы попытаемся немного переделать все это, и в этом случае не будет необходимости освежать. Кэш будет использоваться совместно с помощью Ignite, поэтому для управления перебалансировкой данных требуется сам кластер. Таким образом мы можем забыть обо всем этом. Благодаря! – Kilian