Проверка подхода кэширования с EhCache, Spring и Hibernate - PullRequest
2 голосов
/ 21 декабря 2011

У меня есть приложение, которое реализует соединение Socket для чтения позиционных данных. Каждая позиция относится к активу. Поток обновляет позиционные данные для многих сотен активов в режиме реального времени. Вот базовое представление класса 2-х доменных объектов:

public class Asset{
    long id;
    Set<Position> positions;
}


public class Position{
    long id;
    Double latitude;
    Double longitude;
    Date timestamp
}

Теперь я хочу, чтобы данные о положении за последние 1 день были доступны удаленному клиенту для опроса. Будет много сотен клиентов, делающих запросы на опрос в последний день позиционных данных для каждого актива. Каждый актив будет обновляться с позиционными данными каждые 5 секунд. Требование заключается в том, что запрос клиента может быть не более 10 секунд не синхронизирован с обновлением в реальном времени.

Это создает огромную нагрузку на базу данных - вот куда приходит EHCache - возможно ...

Хорошей альтернативой (сомнительно!) Будет настройка кеша, в котором будут храниться любые новые активы и связанные с ними позиции при их чтении через сокет-соединение. Срок действия этого кэша истечет для любого Актива, который был обновлен более дня назад, и будет отвечать за периодическую запись новых Активов и Позиций в базу данных (каждую минуту или около того). Удаленные клиенты будут попадать в кэш для данных об активах и позициях.

Мне просто хотелось несколько мыслей / советов о том, может ли этот подход быть разумным, а также о том, какие возможности EHCache могут ему помочь.

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

1 Ответ

1 голос
/ 21 декабря 2011

Этот может быть хорошим примером использования для EhCache и Hibernate кеш запросов . Вот основная архитектура. Сначала включите кэш второго уровня для объекта Position. Я думаю, что оно пропускает поле asset, которое представляет отношение один-ко-многим, но это не имеет значения.

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

SELECT p
FROM Position p
WHERE timestamp >= :timestamp
  AND asset = :assert

Параметр :timestamp представляет последние 24 часа (текущее время - 24 часа). Вам необходимо включить подсказку запроса cacheable для этого запроса.

Вот что происходит: клиент выполняет этот запрос косвенно с парой (asset, timestamp) параметров. Hibernate пытается найти результат запроса в кеше запросов для этой пары, которая (упрощенно) составляет ключ кеша запросов.

Если результат запроса отсутствует, он запускает запрос и помещает результаты в кэш запроса. Но он размещает только идентификаторы совпадающих Position экземпляров, а не сами экземпляры. В следующий раз, когда какой-нибудь клиент запросит ту же пару (asset, timestamp), Hibernate найдет результаты в кеше запросов. Затем, имея только идентификаторы, он будет искать Position экземпляров в кэше второго уровня.

Как видите, этот сценарий довольно сложный, и на общий успех повлияют несколько факторов:

  • сколько существует различных пар (asset, timestamp)? Грубо:

.

86400 (number of different seconds in a day) times 
  number of different assets 

ключи и значения должны помещаться в кэш. Помните, что каждое значение является списком Position идентификаторов. Это много памяти. Вы, вероятно, можете сократить это, ограничив количество различных временных меток. Важны ли последние 24 часа? Может ли это быть между 23 и 24 часами или около того? Таким образом, вы можете округлять временные метки и уменьшать размер пространства ключей (размер кэша).

  • Все Position ссылки на экземпляры по идентификатору из кеша запросов должны помещаться в кеш. Это может быть огромным. Но в противном случае вы столкнетесь с проблемой N + 1, так как при отсутствии сущности Position в кэше L2 при извлечении из кэша запросов Hibernate будет выполнять неявный запрос по идентификатору из базы данных.

  • Аннулирование кэша выполняется Hibernate. Однако помните, что каждая вставка в таблицу Position делает кеш запросов недействительным. В ваших обстоятельствах полный разогрев кеша может оказаться невозможным.

При этом вам следует попробовать запросить кеширование в Hibernate. Однако кэш запросов очень сложен и требует много настроек для правильной реализации.

Совет: если вам не хватает памяти, попробуйте переполнить EhCache на диск. Никогда не пробовал, но я верю, что выборочные значения кеша с локального диска (особенно при использовании SSD) могут быть намного быстрее, чем пропадание кеша и запрос к базе данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...