Блокировка иерархии кураторов (перекрывающиеся блокировки)
Я был в состоянии успешно получить блокировку на /ads/lock/0-test1
а потом не смог запереть /ads/lock
Как я могу решить это?
InterProcessMutex lock1 = new InterProcessMutex(client, "/ads/lock/0-test1");
if(lock1.acquire(30000, TimeUnit.MILLISECONDS)){
InterProcessMutex lock2 = new InterProcessMutex(client, "/ads/lock");
if(lock2.acquire(30000, TimeUnit.MILLISECONDS)) { //Failing
...
}
}
Обновление: это суть того, что происходит в этом https://github.com/Microsoft/Cluster-Partition-Rebalancer-For-Kafka/blob/dd63f14b0b854b38dfc8d064987c5dd4b65fb5e2/src/main/java/ZookeeperBackedAdoptionLogicImpl.java Замки в строке 250(подробный путь) и 299(корневой путь) являются последовательными, Таким образом, когда другой экземпляр пытается заблокировать подробный путь (250), блокировка завершается ошибкой, поскольку корневой путь (299) заблокирован. Логика верна, но корневая блокировка никогда не получается
Обновление 2: я написал небольшую программу, чтобы проверить, работают ли перекрывающиеся блокировки и работает ли она.
public class LockTesting {
public static final String ROOT_LOCK = "/locks";
public static final String CHILD_LOCK = ROOT_LOCK+"/child";
private static CuratorFramework client;
public static void main(String[] args) throws Exception {
client = CuratorFrameworkFactory.newClient("127.0.0.1:2181", new ExponentialBackoffRetry(1000, 30));
client.start();
InterProcessMutex lock1 = new InterProcessMutex(client, CHILD_LOCK);
if (lock1.acquire(30000, TimeUnit.MILLISECONDS)) {
System.out.println("Child Locked");
InterProcessMutex lock2 = new InterProcessMutex(client, ROOT_LOCK);
if (lock2.acquire(30000, TimeUnit.MILLISECONDS)) {
System.out.println("Root Locked");
}
}
}
}
1 ответ
Хотя это явно не задокументировано (но см. Примечание 7), механизмы, используемые куратором для создания блокировки, зависят от дочерних узлов конкретного пути znode. InterProcessMutex
является реализацией рецепта блокировки zookeeper, документация которого включает эти детали. Пытаясь использовать иерархическую конструкцию, подобную этой, вы по сути возитесь с внутренней структурой замка.
Путь к блокировке следует рассматривать как "объект", внутренние узлы которого недоступны и могут быть изменены.
Ответ на обновление
Данный код действительно является примером такого неуместного использования.
Ответ на Update2
Да, иногда это может работать. Но это зависит от внутренних деталей InterProcessMutex
реализация. Вы обнаружите, что с некоторыми именами блокировок это будет работать, а с другими - нет, или у вас будет неопределенное поведение.