Наш кластер сервера состоит из 20 машин, каждого с 10 pids 5 потоков. Мы хотели бы некоторый способ предотвратить любые два потока, в любом pid, на любой машине, от изменения того же объекта одновременно.
Наш код записал в Python и работает на Linux, если это помогает отнести узкие вещи.
Кроме того, это - довольно редкий случай, что два таких потока хотят сделать это, таким образом, мы предпочли бы что-то, что оптимизирует "только одну потребность потока этот объектный" случай, чтобы быть действительно быстрым, даже если это означает, что "один поток заблокировал этот объект, и другому нужен он" случай, не является большим.
Что такое некоторые лучшие практики?
Если вы хотите синхронизировать между машинами, вам понадобится Диспетчер распределенных блокировок .
Я быстро погуглил и нашел: Stackoverflow . К сожалению, они предлагают только версию Java, но это только начало.
Если вы пытаетесь синхронизировать доступ к файлам: в вашей файловой системе уже должна быть какая-то служба блокировки. Если нет, подумайте об изменении.
Напишите код, используя неизменяемые объекты. Напишите объекты, реализующие шаблон Singleton.
Используйте стабильную технологию распределенного обмена сообщениями, такую как IPC, веб-службы или XML-RPC.
Я бы посмотрел на Twisted. У них есть масса решений для такой задачи.
Я бы не стал использовать потоки в Python, особенно в отношении GIL, я бы посмотрел на использование процессов в качестве рабочих приложений и использовал бы технологию связи, как описано выше, для взаимодействия.
Затем ваш одноэлементный класс может появиться в одном из этих приложений и взаимодействовать с ним через выбранную технологию связи.
Не быстрое решение со всеми интерфейсами, но, если все сделано правильно, должно быть стабильным.
если вы может получить полную инфраструктуру для распределенного диспетчера блокировок, а затем использовать ее. Но эту инфраструктуру настроить непросто! Но вот практическое решение:
- назначьте узел с наименьшим IP-адресом главным узлом (это означает, что если узел с наименьшим IP-адресом зависнет, новый узел с наименьшим IP-адресом станет новый мастер)
- пусть все узлы связываются с главным узлом, чтобы получить блокировку объекта.
-разрешить главному узлу использовать собственную семантику блокировки для получения блокировки.
это упростит задачу, если для выполнения этой работы вам не понадобится полная инфраструктура кластеризации и DLM.
Полагаю, вы наткнулись на эту статью в блоге http://amix.dk/blog/post/19386 во время гугления?
Автор демонстрирует простой интерфейс к memcachedb, который он использует как фиктивный менеджер распределенных блокировок. Это отличная идея, и memcache, вероятно, одна из самых быстрых вещей, с которыми вы сможете взаимодействовать. Обратите внимание, что здесь используется недавно добавленный оператор with.
Вот пример использования из его сообщения в блоге:
from __future__ import with_statement
import memcache
from memcached_lock import dist_lock
client = memcache.Client(['127.0.0.1:11211'])
with dist_lock('test', client):
print 'Is there anybody out there!?'
Возможно, есть лучший способ сделать это, но я бы использовал класс Lock из модуля threading для доступа к "защищенным" объектам в операторе with, вот пример:
from __future__ import with_statement
from threading import Lock
mylock = Lock()
with mylock.acquire():
[ 'do things with protected data here' ]
[ 'the rest of the code' ]
другие примеры использования Lock можно посмотреть здесь.
Edit: это решение не подходит для данного вопроса, так как threading.Lock не распространяется, извините