Предотвращение нескольких вторичных заселений того же региона кэша (из-за параллелизма)

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

Иначе, очереди сообщений и общая память довольно просты иметь дело с.

13
задан 13 revs 23 May 2017 в 10:30
поделиться

1 ответ

Я не совсем уверен, но:

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

Разве это не означает, что Hibernate будет ждать, пока какой-то другой поток не поместит объект в кеш? Это то, что вы наблюдаете, верно?

Hib и кеш работают следующим образом:

  1. Hib получает запрос на объект
  2. Hib проверяет, находится ли объект в кеше - cache.get ()
  3. Нет? Hib загружает объект из БД и помещает в кеш - cache.put ()

Таким образом, если объект не находится в кеше (не помещен туда какой-либо предыдущей операцией обновления), Hib будет ждать 1) бесконечно.

Я думаю, вам нужен вариант кеширования, в котором поток ожидает объект только в течение короткого времени. Например, 100 мс. Если объект не прибыл, поток должен получить значение NULL (и, таким образом, Hibernate загрузит объект из БД и поместит его в кеш).

На самом деле, лучше логика:

  1. Проверить, что другой поток запрашивает тот же объект
  2. Если верно, долго ждать (500 мс) прибытия объекта
  3. Если не истинно, немедленно вернуть null

(Мы не можем ждать 2 бесконечно, поскольку поток может не поместить объект в кеш - из-за исключения).

Если BlockingCache не поддерживает такое поведение, вам необходимо реализовать кеш самостоятельно. Я делал это раньше, это несложно - основные методы - это get () и put () (хотя API с тех пор явно вырос).

UPDATE

На самом деле, я только что прочитал исходники BlockingCache. Он делает именно то, что я сказал - блокирует и ждет таймаута. Таким образом, вам не нужно ничего делать, просто используйте это ...

public Element get(final Object key) throws RuntimeException, LockTimeoutException {
    Sync lock = getLockForKey(key);
    Element element;
        acquiredLockForKey(key, lock, LockType.WRITE);
        element = cache.get(key);
        if (element != null) {
            lock.unlock(LockType.WRITE);
        }
    return element;
}

public void put(Element element) {
    if (element == null) {
        return;
    }
    Object key = element.getObjectKey();
    Object value = element.getObjectValue();

    getLockForKey(key).lock(LockType.WRITE);
    try {
        if (value != null) {
            cache.put(element);
        } else {
            cache.remove(key);
        }
    } finally {
        getLockForKey(key).unlock(LockType.WRITE);
    }
}

Странно, что это не работает для вас. Скажите мне что-нибудь: в вашем коде это место:

Ehcache cache = manager.getEhcache("foo");

синхронизировано? Если одновременно поступают несколько запросов, будет ли только один экземпляр кеша?

5
ответ дан 2 December 2019 в 01:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: