Форум сайта python.su
32
В больших проектах иногда задействовано много разных компонентов, интересуют технологии поддержки “целостности”.
Например сохраняем документ в 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 - не то которое можно поставить в очередь, а которое влияет на (возможность) сохранение.
Кто как решает подобную задачу, какие есть методики?
Офлайн
49
Задача не решаема в принципе.
Mongo - не поддерживает транзакции, откатить никак, поддержка целостности то что называют “в конечном счете”.
Для целостности нужно использовать CP-системы, например Zookeeper.
Sphinx сам по себе подразумевает возможность ошибок в поиске, ибо отвязан от базы, полнотекстовый поиск “есть” в самой mongo (правда сильно медленней sphinx).
В общем простых решений нет.
Офлайн
253
Ну а по технологии откатывания: обычно используем связный список обработчиков с рекурсивным спуском при обработке и откатом по try …except.
Офлайн
49
doza_and
Ну а по технологии откатывания: обычно используем связный список обработчиков с рекурсивным спуском при обработке и откатом по try …except.
Офлайн
47
нужны транзакции на уровне приложения и операции должны поддерживать возможность отката
в пирамиде есть такое искаропки, для других можно слепить на основе 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, концепция взята оттуда, зависимости от зопы уже нет
Офлайн
32
AlenДа, имел ввиду Eventual consistency
Задача не решаема в принципе.
поддержка целостности то что называют “в конечном счете”.
AlenМне кажется он не сколько медленный, сколько требовательный к ресурсам, на одном проекте сильно жрет оперативку.
полнотекстовый поиск “есть” в самой mongo (правда сильно медленней sphinx).
doza_andИнтересный вариант, но тут 2 проблемы:
Ну а по технологии откатывания: обычно используем связный список обработчиков с рекурсивным спуском при обработке и откатом по try …except.
Alen2) Если например sphinx берет текущее значение из БД для обновления, то при откате, sphinx нужно вызывать в конце, хотя конкретно для сфинкса не обязательно, можно держать старое значение для отката. Можно ли так покрыт все случаи?
дает непредсказуемый результат в случае распада системы.
Офлайн
49
o7412369815963
Да, имел ввиду Eventual consistency
Отредактировано Alen (Янв. 24, 2015 22:05:35)
Офлайн
32
AlenУ меня в голове другой вариант, в момент “транзакции”, каждый шаг (sphinx/api…) вначале регистрирует свой rollback метод с приоритетом в документ транзакции, далее выполняет необходимые действия.
необходимо хранить текущий статус операций в mongo
AlenЭта рекомендация уже не так актуальна, т.к. журнал дает сопоставимую *sql'ям надежность в пределах одной ноды.
естественно реплицированной 3 узла минимум
Офлайн
32
AlenПочему для каждой операции свои воркеры?
Т.е. для каждой операции свой набор воркеров работающих независимо
Офлайн
49
o7412369815963
Эта рекомендация уже не так актуальна, т.к. журнал дает сопоставимую *sql'ям надежность в пределах одной ноды.
o7412369815963
Почему для каждой операции свои воркеры?
Мне кажется вариант, где все воркеры умеют выполнять любые операции, лучше. - просто “докидывать” один и тот же воркер на сервера если нужно больше производительности.
Офлайн