Почему мне нужно использовать куратор, а не собственный API зоопарка в качестве распределенной блокировки?

Наш проект сильно зависит от распределенной блокировки. Я знаю, что куратор предоставляет несколько видов замков. Мой вопрос: могу ли я просто использовать создающий узел в качестве мьютекса?

CuratorFramework zkClient = zookeeperConnectionProvider.getZkClientForJobDistributeLock();
            try {
                zkClient.create()
                        .creatingParentsIfNeeded()
                        .withMode(CreateMode.EPHEMERAL)
                        .forPath("/" + job.getIdentifier().jobNodeString());
                LOGGER.info(String.format("create node in zookeeper [%s]", job.getIdentifier().jobNodeString()));
            } catch (Exception e) {
                LOGGER.info(String.format("create job instance node in zookeeper failed [%s], reason [%s]",
                        job.getIdentifier().jobNodeString(),
                        e.getClass().getCanonicalName()));
                return NO_WORK;
            }

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


person Jie Liu    schedule 17.02.2016    source источник


Ответы (1)


Я думаю, что первое возражение против того, как вы предлагаете, заключается в том, что код трудно читать/понимать, сравните его с:

InterProcessSemaphoreMutex lock = new InterProcessSemaphoreMutex(client, path);
lock.acquire();

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

//do normal work
...
lock.acquire();
//do critical single threaded work
...
lock.release();
//back to normal work
...

Что вполне возможно с вашим кодом, но здесь он создан для вас.


Есть гораздо больше причин использовать уже реализованную блокировку вместо того, чтобы писать свою собственную, но в основном они сводятся к следующему: «Зачем изобретать велосипед?»

person Petter    schedule 19.02.2016
comment
Спасибо, Петтер. Что мне нужно, так это что-то вроде мьютекса, но неудавшийся процесс не должен ждать, пока выполнится успешный выпуск. Я думал, что узел именования в zookeeper будет в порядке, но обнаружил, что он вообще не работает. Наконец, я обращаюсь к InterProcessMutex. Причина, по которой я не использовал его в начале, заключается в том, что я прочитал некоторые документы, зная, что он создает несколько узлов в zookeeper, и минимальный индекс получит блокировку. - person Jie Liu; 21.02.2016
comment
Поэтому я подумал, что один узел может быть более эффективным. После этого я провел несколько экспериментов: процесс A создает узел в zookeeper и сохраняет соединение, затем процесс B удаляет узел, я получаю исключение NoNode. Если процесс A отключился от сервера zookeeper, процесс B может удалить его корректно (ps: тип узла — CreateMode.Persistent). Есть ли какой-то механизм изоляции между разными соединениями? - person Jie Liu; 21.02.2016
comment
Если вы не хотите ждать блокировки, вы можете использовать: Boolean hasLock = lock.acquire(1, TimeUnit.MILLISECONDS); Я не уверен, что вы можете использовать 0, но это будет ждать блокировки только 1 миллисекунду, поэтому это не должно сильно замедлять ваш код. О, и если «hasLock» ложно, вы не получили блокировку. - person Petter; 21.02.2016