Обнаружение мертвого замка - Gemfire 8

Я определил регион GemFire ​​с помощью RegionShortcut.PARTITION и setRedundantCopies(1). В этом регионе используются 3 приложения, работающие на 3 разных виртуальных машинах.

Кажется, что у меня есть мертвая блокировка, когда я закрываю виртуальную машину приложения, которое только что вставило элемент в кеш ("владелец" элемента):

* Заблокированный процесс: заблокирован до region.put.

* Процесс блокировки: кажется, заблокирован после попытки удалить старые записи из региона. Я подозреваю, что эта операция вызывается механизмом уничтожения, предоставленным CacheListenerAdapter.

Я прочитал некоторую документацию по этой проблеме по следующим ссылкам: API-интерфейс CacheListener и этот блог, в котором виноваты в основном слушатели.

Тем не менее, кажется, что эти проблемы были решены и исправлены в версиях GemFire ​​6.x [например: здесь и здесь]

Итак, я хотел бы спросить:

1) Сообщается ли об этих проблемах для Gemfire 8? или 7?

2) Каков рекомендуемый способ решения этой проблемы? 3 различных обходных пути упомянуты здесь. Есть ли другие? Любой предпочтительный?

Для справки: дамп потока блокирующего процесса выглядит следующим образом:

Owner stack trace: java.lang.Throwable
    at sun.misc.Unsafe.park(Native Method)
    at java.util.concurrent.locks.LockSupport.park(Unknown Source)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(Unknown Source)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(Unknown Source)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(Unknown Source)
    at java.util.concurrent.locks.ReentrantReadWriteLock$ReadLock.lockInterruptibly(Unknown Source)
    at com.gemstone.gemfire.internal.cache.BucketRegion.lockPrimaryStateReadLock(BucketRegion.java:780)
    at com.gemstone.gemfire.internal.cache.BucketRegion.doLockForPrimary(BucketRegion.java:719)
    at com.gemstone.gemfire.internal.cache.BucketRegion.beginLocalWrite(BucketRegion.java:704)
    at com.gemstone.gemfire.internal.cache.BucketRegion.basicDestroy(BucketRegion.java:1105)
    at com.gemstone.gemfire.internal.cache.PartitionedRegionDataStore.destroyLocally(PartitionedRegionDataStore.java:1511)
    at com.gemstone.gemfire.internal.cache.PartitionedRegion.destroyInBucket(PartitionedRegion.java:5440)
    at com.gemstone.gemfire.internal.cache.PartitionedRegionDataView.destroyExistingEntry(PartitionedRegionDataView.java:45)
    at com.gemstone.gemfire.internal.cache.PartitionedRegion.basicDestroy(PartitionedRegion.java:5317)
    at com.gemstone.gemfire.internal.cache.LocalRegion.validatedDestroy(LocalRegion.java:1330)
    at com.gemstone.gemfire.internal.cache.LocalRegion.destroy(LocalRegion.java:1317)
    at com.gemstone.gemfire.internal.cache.AbstractRegion.destroy(AbstractRegion.java:282)
    at com.gemstone.gemfire.internal.cache.LocalRegion.remove(LocalRegion.java:9513)

1 ответ

Возможны взаимоблокировки с использованием CacheListeners. Поведение задокументировано в последнем (GemFire ​​8.1) javadoc. Вот соответствующая выдержка из документации CacheListener:

Как избежать риска тупика

Методы в CacheListener вызываются, удерживая блокировку записи, описанной EntryEvent, в результате, если метод слушателя занимает много времени для выполнения, то это приведет к тому, что вызвавшая его операция займет много времени. Кроме того, код слушателя, который вызывает методы Region, может привести к тупику. Например, в afterUpdate(EntryEvent) для ключа входа k1, put(k2, someVal) вызывается одновременно с afterUpdate(EntryEvent) для вызовов ключа k2 вызовов put(k1, someVal) может привести к взаимоблокировке. Этот пример зависимости вспомогательного ключа может быть расширен до зависимости вспомогательного региона, где код прослушивателя в области "A" выполняет операции области для "B", а код прослушивателя в области "B" выполняет операции области для "A". В зависимости от конфигурации региона взаимные блокировки могут быть либо на уровне Java, либо в виде распределенных мертвых блокировок на несколько виртуальных машин Чтобы быть уверенным в отсутствии взаимоблокировок, код прослушивателя должен вызывать доступ к региону другого потока и не должен ждать, пока этот поток завершит задачу.

Другие вопросы по тегам