2014-09-16 2 views
3

У меня довольно стандартная настройка уровня сохранения в приложении Spring с использованием Hibernate (4.2.15.Final) с EhCache (2.6.9) в качестве кэша второго уровня.EhCache Hibernate кэш второго уровня maxBytesLocalHeap slow

Все работает должным образом. Однако ввод записей в кеш второго уровня иногда занимает много времени.

Я настроил кэширование моей модели домена классов в явном ehcache.xml файл (я не настроить кэш по умолчанию):

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd" 
     name="hibernate" 
     updateCheck="false" 
     monitoring="autodetect" 
     dynamicConfig="false" 
     maxBytesLocalHeap="300M" 
     maxBytesLocalDisk="500M"> 

    <cache 
    name="org.mycorp.model.MyEntity" 
    eternal="true" 
    overflowToDisk="false" 
    diskPersistent="false" 
    maxBytesLocalHeap="5M" /> 

    ... 

</ehcache> 

Я получаю следующее сообщение INFO регистрируется при запуске контекста инерционности :

DefaultSizeOfEngine | using Agent sizeof engine 

и следующее предупреждение во время выполнения

ObjectGraphWalker | The configured limit of 1,000 object references was reached while attempting to calculate the size of the object graph. Severe performance degradation could occur if the sizing operation continues. [...] 

AFAIK ObjectGraphWalker должен оценивать объекты, помещенные в кеш, поскольку я сконфигурировал отдельные области кеша с помощью maxBytesLocalHeap.

Моя модель предметной области является довольно сложным, и я знаю, что я могу ограничить ходьбу графа с @IgnoreSizeOf аннотаций, но я не зная, как решить эту проблему:

  • Должен ли я игнорировать одну сторону двунаправленной ассоциации, чтобы избежать циклов?
  • Должен ли я явно игнорировать переходные члены классов модели домена?
  • В целом, разумно ли идти с maxBytesLocalHeap при использовании EhCache вместе с Hibernate, или мне нужно установить для maxEntriesLocalHeap, потому что Hibernate сохраняет отдельную область кэша для каждого объекта?

[UPDATE]: Я обнаружил, что временные члены не будут кэшировать Hibernate (см Hibernate: Is it possible to save a transient field in second level cache?), поэтому они не должны быть расценены Ehcache в любом случае. Верный?

ответ

3

Короткий ответ

Оказывается, что проблема у меня есть результат использования экземпляров Joda-Time в моей модели (я использую Jadira's UserType library для отображения типов Joda).

Типы Joda содержат всевозможные внутренние ссылки (включая ссылки на хронологическую информацию, приводящую к огромному графу объектов), а SizeOfEngine Ehcache выполняет эти ссылки, ведущие к моему первоначальному предупреждению.

Не нашел чистого способа настройки механизма SizeOfEngine, чтобы исключить эти ссылки, но опять же, я думаю, что более чистый подход состоял бы в том, чтобы заставить Hibernate помещать только соответствующую информацию в кеш второго уровня (a время в моем случае LocalDateTimes).

Update

Jadira сделал плохой выбор при реализации своих собственных типов: См my answer here

Подробнее Подробнее

Вот что я нашел по поводу моего OP (с использованием Hibernate 4.2.15. Final, EhCache 2.6.9 и UserType 3.2.0.GA):

Прежде всего, у меня было неправильное представление о том, как H ibernate хранит объекты в кэше второго уровня. После прочтения записи блога Лоримеру в о Truly Understanding the Second-Level and Query Caches много вещей, сделанных больше смысла для меня:

  • Вам не придется беспокоиться о двунаправленных ассоциаций (или циклических графов на то пошло), потому что Hibernate будет только положить идентификаторы для вашего ассоциаций в кеш. И даже если бы он помещал ссылку на весь объект в кеш, а это не так - EOKache's SizeOf Engine будет отслеживать объекты в уже посещенном графике и не будет изменять их дважды.
  • Опять же, вам не нужно беспокоиться о переходных полях, потому что Hibernate не будет помещать их в кеш
  • В теории не должно возникнуть никаких проблем с конфигурацией maxBytesLocalHeap. В настоящее время проблемы возникают, когда вы используете пользовательские типы пользователей, которые неправильно измеряются механизмом SizeOf EhCache.
1

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

И наконец, я нашел this page и решить его.

+0

Я исследовал эту статью, и наша проблема не была связана вообще с Hibernate; на самом деле ehcache 2.10.3 и, возможно, более ранние версии имеют предварительно сконфигурированный фильтр, который кажется правильным ('ehcache-2.10.3.jar!/net/sf/ehcache/pool/builtin-sizeof.filter'). Статья интересна тем, что я нашел способ найти, какая запись была добавлена ​​в кэш, включив журнал отладки в 'net.sf.ehcache.pool' и установив' static {System.setProperty ("net.sf.ehcache.sizeof. verboseDebugLogging "," true "); } '. Оказалось, что это сервис, аннотированный Spring '@ Cacheable', который возвращал« ResourceBundle ». – Brice

Смежные вопросы