Я работаю над REST API для веб-службы, используя Pyramid и Карниз; данные на стороне сервера обрабатываются с помощью SQLAlchemy и MySQL. Веб-сервер — это nginx, использующий uwsgi и настроен на запуск нескольких процессов Python:
[uwsgi]
socket = localhost:6542
plugins = python34
...
processes = 2 # spawn the specified number of workers/processes
threads = 2 # run each worker in prethreaded mode with the specified number of threads
Проблема
Предположим, таблица customers
на стороне сервера. С помощью API можно читать данные о клиентах, изменять их или удалять. В дополнение к этому есть другие функции API, которые считывают данные клиентов.
Я мог бы одновременно выполнять несколько вызовов API, которые затем конкурировали бы за один и тот же ресурс клиента:
# Write/modify the customer {id} data
curl --request POST ... https://some.host/api/customer/{id}
# Delete customer {id} and all of its associated data
curl --request DELETE https://some.host/api/customer/{id}
# Perform some function which reads customer {id}
curl --request GET ... https://some.host/api/do-work
По сути, это Проблема читателей-писателей, но поскольку задействован процесс, традиционная синхронизация потоков с использованием блокировок/мьютексов/семафоров не будет работать здесь.
Вопрос
Я хотел бы понять, как лучше всего реализовать блокировку и синхронизацию для такого веб-API на основе пирамиды, чтобы одновременные вызовы, как в приведенном выше примере, обрабатывались безопасно и эффективно (т.е. без ненужной сериализации).
Решения (?)
- Я не думаю, что имеет смысл отмечать/отмечать клиента
{id}
какlocked
, потому что SQLAlchemy кэширует такие изменения иflush()
не кажется достаточно атомарным в этом контексте? - В этой статье описывается использование HTTP ETag для управления общими ресурсами.
- Можно также использовать Redis в качестве ссылки диспетчер распределенных блокировок для спин-блокировки для переноса функции просмотра?
- Как насчет менеджера транзакций от Pyramid?