Форум сайта python.su
В больших проектах иногда задействовано много разных компонентов, интересуют технологии поддержки “целостности”.
Например сохраняем документ в MongoDB и при этом нужно обновить зависимый документ, обновить sphinx/elastic, отправить письмо, вызвать АПИ и т.п.
При этом если произойдет проблема на середине процесса (ошибки или хост потухнет), нужно будет все откатить.
По хорошему обработчики должны “навешиваться”, т.е. подключаем плагин, а он добавляет обработчик при сохранении пользователя (например db.user.add_trigger(some_method) или т.п.)
Например есть такой список обработчиков на сохранении:
1) Сохранение документа в БД
2) Вызвать API1
3) Обновление записи в sphinx/elastic
4) Отправка Email
5) Сохранение под-документа в БД
6) Отправить событие через websocket
7) Вызвать API2
С Email обычно проблем нет - добавляется задача в очередь, откатывать нечего (ну или отправить отменяющее письмо, а лучше вызвать это в конце процесса).
Транзакционные базы решают только сохранение в БД, т.е. всего 2 пункта из 7, не достаточно, или если там отдельная “sql”.
А вот с sphinx и API уже интересней, sphinx нужно будет откатить (удалить/записать старые данные), для АПИ - вызвать отменяющий/дополнительный метод.
Пример с API - не то которое можно поставить в очередь, а которое влияет на (возможность) сохранение.
Кто как решает подобную задачу, какие есть методики?
Офлайн
Задача не решаема в принципе.
Mongo - не поддерживает транзакции, откатить никак, поддержка целостности то что называют “в конечном счете”.
Для целостности нужно использовать CP-системы, например Zookeeper.
Sphinx сам по себе подразумевает возможность ошибок в поиске, ибо отвязан от базы, полнотекстовый поиск “есть” в самой mongo (правда сильно медленней sphinx).
В общем простых решений нет.
Офлайн
Ну а по технологии откатывания: обычно используем связный список обработчиков с рекурсивным спуском при обработке и откатом по try …except.
Офлайн
doza_and
Ну а по технологии откатывания: обычно используем связный список обработчиков с рекурсивным спуском при обработке и откатом по try …except.
Офлайн
нужны транзакции на уровне приложения и операции должны поддерживать возможность отката
в пирамиде есть такое искаропки, для других можно слепить на основе repoze аналогов
есть такой пакет https://pypi.python.org/pypi/transaction
в пирамиде есть такой мидлваре https://pypi.python.org/pypi/pyramid_tm
который оборачивает запрос, если небыло ексепшенов в конце вызывается transaction.commit()
(wsgi аналог https://pypi.python.org/pypi/repoze.tm)
https://pypi.python.org/pypi/zope.sqlalchemy
подключает sqlalchemy транзакции к общей транзакции
https://pypi.python.org/pypi/pyramid_mailer
делает отправку мыла transaction aware
(аналог https://pypi.python.org/pypi/repoze.sendmail)
вижу вот такое есть еще https://pypi.python.org/pypi/pyramid_transactional_celery
для остальных операций нужно написать соответсвующие менеджеры :)
P.S. в доках и в названии пакетов не обращать внимание на упоминание ZOPE, концепция взята оттуда, зависимости от зопы уже нет
Офлайн
AlenДа, имел ввиду Eventual consistency
Задача не решаема в принципе.
поддержка целостности то что называют “в конечном счете”.
AlenМне кажется он не сколько медленный, сколько требовательный к ресурсам, на одном проекте сильно жрет оперативку.
полнотекстовый поиск “есть” в самой mongo (правда сильно медленней sphinx).
doza_andИнтересный вариант, но тут 2 проблемы:
Ну а по технологии откатывания: обычно используем связный список обработчиков с рекурсивным спуском при обработке и откатом по try …except.
Alen2) Если например sphinx берет текущее значение из БД для обновления, то при откате, sphinx нужно вызывать в конце, хотя конкретно для сфинкса не обязательно, можно держать старое значение для отката. Можно ли так покрыт все случаи?
дает непредсказуемый результат в случае распада системы.
Офлайн
o7412369815963
Да, имел ввиду Eventual consistency
Отредактировано Alen (Янв. 24, 2015 22:05:35)
Офлайн
AlenУ меня в голове другой вариант, в момент “транзакции”, каждый шаг (sphinx/api…) вначале регистрирует свой rollback метод с приоритетом в документ транзакции, далее выполняет необходимые действия.
необходимо хранить текущий статус операций в mongo
AlenЭта рекомендация уже не так актуальна, т.к. журнал дает сопоставимую *sql'ям надежность в пределах одной ноды.
естественно реплицированной 3 узла минимум
Офлайн
AlenПочему для каждой операции свои воркеры?
Т.е. для каждой операции свой набор воркеров работающих независимо
Офлайн
o7412369815963
Эта рекомендация уже не так актуальна, т.к. журнал дает сопоставимую *sql'ям надежность в пределах одной ноды.
o7412369815963
Почему для каждой операции свои воркеры?
Мне кажется вариант, где все воркеры умеют выполнять любые операции, лучше. - просто “докидывать” один и тот же воркер на сервера если нужно больше производительности.
Офлайн