Коли і як використовувати сплячий кеш другого рівня?


90

У мене проблеми з розумінням, коли сплячий режим потрапляє в кеш другого рівня, і коли це робить кеш недійсним.

Це те, що я зараз розумію:

  • Кеш-пам’ять другого рівня зберігає сутності між сесіями, область дії - SessionFactory
  • Ви повинні сказати, які сутності кешувати, жодна сутність не буде кешована за замовчуванням
  • Кеш запитів зберігає результати запитів у кеші.

Чого я не розумію, так це

  • Коли сплячий режим потрапляє в цей кеш?
  • Скажімо, я встановив кеш другого рівня, але не кешування запитів. Я хочу кешувати своїх клієнтів, їх там 50000. Якими способами я можу отримати клієнтів із кешу?
  • Я припускаю, що я можу отримати їх за допомогою ідентифікатора з кешу. Це було б легко, але також не гідно кешувати. Але що, якщо я хочу зробити якийсь розрахунок з усіма своїми клієнтами. Скажімо, я хочу показати список клієнтів, як я тоді можу отримати до них доступ?
  • Як я можу отримати всіх своїх клієнтів, якщо кешування запитів вимкнено?
  • Що було б, якби хтось оновив когось із клієнтів?
    • Чи був би цей клієнт недійсним у кеш-пам’яті чи всі клієнти втратили б силу?

Або я думаю, що кешування абсолютно помилкове? Що було б більш доцільним використанням кешу другого рівня в такому випадку? Документація сплячого режиму зовсім не зрозуміла, як кеш працює насправді. Є лише вказівки щодо того, як його налаштувати.

Оновлення: Отже, я зрозумів, що кеш другого рівня (без кешу запитів) був би корисним для завантаження даних за ідентифікаторами. Наприклад, у мене є користувацький об'єкт, який я хочу перевірити на наявність дозволів у кожному запиті у веб-програмі. Чи був би це гарний випадок для зменшення доступу до бази даних, кешуючи користувача в кеші другого рівня? Як би я зберігав ідентифікатор користувача в сеансі або де завгодно, і коли мені потрібно перевірити наявність дозволів, я завантажував би користувача за його ідентифікатором та перевіряв дозволи.


Відповіді:


100

Перш за все, давайте поговоримо про кеш рівня процесу (або кеш 2-го рівня, як вони називають його в режимі глибокого сну). Щоб це працювало, вам слід

  1. налаштувати постачальника кешу
  2. скажіть сплячому режиму, які сутності кешувати (прямо у файлі hbm.xml, якщо ви використовуєте такий тип зіставлення).

Ви повідомляєте постачальнику кеш-пам’яті, скільки об’єктів він повинен зберігати і коли / чому їх слід анулювати. Отже, припустимо, у вас є сутності Book і Author, кожного разу, коли ви отримуєте їх із БД, лише ті, які не знаходяться в кеші, будуть обрані з власне БД. Це значно підвищує продуктивність. Це корисно, коли:

  • Ви пишете в базу даних лише за допомогою режиму глибокого сну (оскільки для цього потрібно знати, коли потрібно змінити або зробити недійсними сутності в кеші)
  • Ви часто читаєте предмети
  • У вас є один вузол, і у вас немає реплікації. В іншому випадку вам доведеться відтворити сам кеш (використовуйте розподілені кеші, такі як JGroups), що додає більшої складності, і це не так добре, як додатки, що не використовують спільний доступ.

Отже, коли працює кеш?

  • Коли ти session.get()абоsession.load() об'єкт, який раніше був виділений і знаходиться в кеш-пам’яті. Кеш - це сховище, де ID є ключем, а властивості - значеннями. Отже, лише коли існує можливість пошуку за ідентифікатором, ви можете виключити потрапляння в БД.
  • Коли ваші асоціації ледаче завантажуються (або охоче завантажуються з селектами замість об’єднань)

Але це не працює, коли:

  • Якщо ви не вибрали за ідентифікатором. Знову ж таки - кеш 2-го рівня зберігає карту ідентифікаторів сутностей до інших властивостей (насправді зберігається не об’єкти, а самі дані), тому, якщо ваш пошук виглядає так:, from Authors where name = :nameтоді ви не натиснете кеш.
  • Коли ви використовуєте HQL (навіть якщо використовуєте where id = ?).
  • Якщо у вашому відображенні ви встановили fetch="join", це означає, що для завантаження асоціацій об'єднання будуть використовуватися скрізь замість окремих операторів вибору. Кеш на рівні процесу працює з дочірніми об'єктами, лише якщо fetch="select"він використовується.
  • Навіть якщо у вас є, fetch="select"але тоді в HQL ви використовуєте об’єднання для вибору асоціацій - ці об’єднання видаються відразу, і вони замінять все, що ви вказали в hbm.xml або анотаціях.

Тепер про кеш запитів. Слід зазначити, що це не окремий кеш, це доповнення до кешу рівня процесу. Скажімо, у вас є організація Country. Це статично, тому ви знаєте, що кожного разу, коли ви скажете, буде встановлено однаковий результат from Country. Це ідеальний кандидат для кешування запитів, він буде зберігати список ідентифікаторів сам по собі, і коли ви наступного разу оберете всі країни, він поверне цей список до кешу рівня процесу, а останній, у свою чергу, поверне об’єкти для кожного ідентифікатора оскільки ці об'єкти зберігаються вже в кеші 2-го рівня. Кеш запитів стає недійсним щоразу, коли що-небудь, що стосується сутності, змінюється. Отже, припустимо, ви налаштували from Authorsрозміщення в кеші запитів. Це не буде ефективним, оскільки Автор часто змінюється.


Чи вимагає запит "від автора завантаження приєднатися до a.books" кеш-запит для отримання авторів із кешу?
palto

1
Ні, кеш запитів призначений лише для статичних даних, і він зберігає лише ідентифікатори. Автори будуть взяті з кешу 2-го рівня.
Станіслав Башкирцев

@ctapobep: неправда, що ти кажеш! "від автора вилучити приєднатися до a.books" чудово працює, якщо польові книги сутності Автор зазначено (примітка ЕАГЕР) ... занадто пізно, я думаю
Bilal BBB

Така чудова відповідь! Я запам’ятаю це весь час! : d
Мохаммадреза Хатамі

після увімкнення "кешу запитів", чи отримує він дані з кешу, якщо ви вибрали іншу властивість, крім ідентифікатора?
Арун

41
  • кеш 2-го рівня - це сховище ключ-значення. Це працює, лише якщо ви отримуєте свої сутності за ідентифікатором
  • кеш-пам’ять 2-го рівня стає недійсною / оновлюється для кожного об’єкта, коли об’єкт оновлюється / видаляється за допомогою сплячого режиму. Це не втрачає чинності, якщо база даних оновлюється іншим способом.
  • для запитів (наприклад, списку клієнтів) використовуйте кеш запитів.

Насправді корисно мати розподілений кеш ключ-значення - це те, що є memcached, і це забезпечує Facebook, Twitter та багато іншого. Але якщо у вас немає пошуку за ідентифікатором, це буде не дуже корисно.


12

Пізно на вечірку, але хотів систематично відповісти на це питання, яке задають багато розробників.

Розглядаючи одне за одним ваше запитання, ось моя відповідь.

З. Коли сплячий режим потрапляє в цей кеш?

А. Кеш першого рівня пов'язаний з об'єктом Session . Другий рівень кеша пов'язаний з об'єктом Factory Session . Якщо об'єкт не знайдено в першому, тоді перевіряється другий рівень.

Q. Скажімо, я налаштував кеш-пам’ять другого рівня, але не кешування запитів. Я хочу кешувати своїх клієнтів, їх там 50000. Якими способами я можу отримати клієнтів із кешу?

А. Ви отримали відповідь у своєму оновленні. Крім того, кеш запитів зберігає лише список ідентифікаторів об'єкта, і ці об'єкти з їх ідентифікаторами зберігаються в одному кеші другого рівня. Отже, якщо ви ввімкнете кеш запитів, ви будете використовувати той самий ресурс. Охайний, правда?

З: Я припускаю, що я можу отримати їх за допомогою ідентифікатора з кешу. Це було б легко, але також не гідно кешувати. Але що, якщо я хочу зробити якийсь розрахунок з усіма своїми клієнтами. Скажімо, я хочу показати список клієнтів, як я тоді можу отримати до них доступ?

А. Відповіли вище.

З. Як я можу отримати всіх своїх клієнтів, якщо кешування запитів вимкнено?

А. Відповіли вище.

З: Що було б, якби хтось оновив когось із клієнтів? Чи був би цей клієнт недійсним у кеш-пам’яті чи всі клієнти втратили б силу?

О. Hibernate не уявляє, але ви можете використовувати інші сторонні IMDG / розподілені кеші, які будуть реалізовані як сплячий кеш другого рівня, і зробити їх недійсними. наприклад, TayzGrid - це один із таких продуктів, і я думаю, їх є більше.


0

Кеш-пам’ять другого рівня Hibernate трохи складно зрозуміти та реалізувати. Ось що ми можемо сказати на основі ваших запитань:

Коли Hibernate потрапляє в цей кеш?

Як ви пропонуєте, кеш Hibernate L2 (якщо ввімкнено; він не ввімкнений за замовчуванням) запитується лише після кешу L1. Це кеш-значення значення, дані якого зберігаються протягом декількох сеансів.

Скажімо, я встановив кеш другого рівня, але не кешування запитів. Я хочу кешувати своїх клієнтів, їх там 50000. Якими способами я можу отримати клієнтів із кешу?

Кешування запитів було б найкращим для цього випадку використання, оскільки дані клієнта є статичними та отримуються з реляційної бази даних.

Що було б, якби хтось оновив когось із клієнтів? Чи був би цей клієнт недійсним у кеш-пам’яті чи всі клієнти втратили б силу?

Це залежить від конкретної стратегії кешування Hibernate, яку ви використовуєте. Hibernate насправді має чотири різні стратегії кешування:

READ_ONLY : Об’єкти не змінюються жодного разу в кеші.

NONSTRICT_READ_WRITE : Об'єкти змінюються (з часом) після оновлення відповідного запису в базі даних; це гарантує остаточну послідовність.

READ_WRITE : Об'єкти змінюються (негайно) після оновлення відповідного запису в базі даних; це гарантує сильну консистенцію за допомогою "м'яких" замків.

ТРАНСАКЦІЙНИЙ : Об’єкти змінюються за допомогою розподілених транзакцій XA, забезпечуючи цілісність даних; це гарантує або повний успіх, або скасування всіх змін. Однак у всіх чотирьох цих випадках оновлення одного запису в базі даних не призведе до недійсності всього списку клієнтів у кеші. Hibernate трохи розумніший за це :)

Щоб дізнатись більше про те, як працює кешування L2 у режимі глибокого сну, ви можете ознайомитися зі статтею „Що таке кеш-пам’ять L2 в режимі глибокого сну” або поглибленою статтею Кешування в режимі глибокого сну за допомогою Redis

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.