Уведомления

Группа в Telegram: @pythonsu

#1 Янв. 24, 2015 19:35:25

o7412369815963
От:
Зарегистрирован: 2009-06-17
Сообщения: 1986
Репутация: +  32  -
Профиль   Отправить e-mail  

События в транзакциях

В больших проектах иногда задействовано много разных компонентов, интересуют технологии поддержки “целостности”.
Например сохраняем документ в 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 - не то которое можно поставить в очередь, а которое влияет на (возможность) сохранение.

Кто как решает подобную задачу, какие есть методики?

Офлайн

#2 Янв. 24, 2015 20:06:27

Alen
Зарегистрирован: 2013-08-01
Сообщения: 373
Репутация: +  49  -
Профиль   Отправить e-mail  

События в транзакциях

Задача не решаема в принципе.

Mongo - не поддерживает транзакции, откатить никак, поддержка целостности то что называют “в конечном счете”.
Для целостности нужно использовать CP-системы, например Zookeeper.

Sphinx сам по себе подразумевает возможность ошибок в поиске, ибо отвязан от базы, полнотекстовый поиск “есть” в самой mongo (правда сильно медленней sphinx).

В общем простых решений нет.

Офлайн

#3 Янв. 24, 2015 20:14:00

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  252  -
Профиль   Отправить e-mail  

События в транзакциях

Ну а по технологии откатывания: обычно используем связный список обработчиков с рекурсивным спуском при обработке и откатом по try …except.



Офлайн

#4 Янв. 24, 2015 20:24:53

Alen
Зарегистрирован: 2013-08-01
Сообщения: 373
Репутация: +  49  -
Профиль   Отправить e-mail  

События в транзакциях

doza_and
Ну а по технологии откатывания: обычно используем связный список обработчиков с рекурсивным спуском при обработке и откатом по try …except.

Ну то есть внешний обработчик, который поддерживает целостность и возможность отката, но дает непредсказуемый результат в случае распада системы.

Может это карта как-то поможет.

Офлайн

#5 Янв. 24, 2015 20:29:44

bismigalis
Зарегистрирован: 2010-10-02
Сообщения: 449
Репутация: +  47  -
Профиль   Отправить e-mail  

События в транзакциях

нужны транзакции на уровне приложения и операции должны поддерживать возможность отката

в пирамиде есть такое искаропки, для других можно слепить на основе 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, концепция взята оттуда, зависимости от зопы уже нет

Офлайн

#6 Янв. 24, 2015 20:43:54

o7412369815963
От:
Зарегистрирован: 2009-06-17
Сообщения: 1986
Репутация: +  32  -
Профиль   Отправить e-mail  

События в транзакциях

Alen
Задача не решаема в принципе.
поддержка целостности то что называют “в конечном счете”.
Да, имел ввиду Eventual consistency

Alen
полнотекстовый поиск “есть” в самой mongo (правда сильно медленней sphinx).
Мне кажется он не сколько медленный, сколько требовательный к ресурсам, на одном проекте сильно жрет оперативку.

doza_and
Ну а по технологии откатывания: обычно используем связный список обработчиков с рекурсивным спуском при обработке и откатом по try …except.
Интересный вариант, но тут 2 проблемы:
1)
Alen
дает непредсказуемый результат в случае распада системы.
2) Если например sphinx берет текущее значение из БД для обновления, то при откате, sphinx нужно вызывать в конце, хотя конкретно для сфинкса не обязательно, можно держать старое значение для отката. Можно ли так покрыт все случаи?

Офлайн

#7 Янв. 24, 2015 21:29:30

Alen
Зарегистрирован: 2013-08-01
Сообщения: 373
Репутация: +  49  -
Профиль   Отправить e-mail  

События в транзакциях

o7412369815963
Да, имел ввиду Eventual consistency

Ну тогда у вас для этого всё есть, необходимо хранить текущий статус операций в mongo ибо она как раз BASE-архитектуры (естественно реплицированной 3 узла минимум).

Т.е. для каждой операции свой набор воркеров работающих независимо (ходящих в монгу по таймауту с блокировками при выполнениями и снятию блокировок по таймауту (отдельный воркер) в случае падения воркеров). Неплохо бы чтобы воркеры гадили о своих проблемах куда-нибудь в Sentry.

Отредактировано Alen (Янв. 24, 2015 22:05:35)

Офлайн

#8 Янв. 24, 2015 22:09:34

o7412369815963
От:
Зарегистрирован: 2009-06-17
Сообщения: 1986
Репутация: +  32  -
Профиль   Отправить e-mail  

События в транзакциях

Alen
необходимо хранить текущий статус операций в mongo
У меня в голове другой вариант, в момент “транзакции”, каждый шаг (sphinx/api…) вначале регистрирует свой rollback метод с приоритетом в документ транзакции, далее выполняет необходимые действия.
В итоге каждая транзакция может иметь свою цепочку rollback - зависит от логики.

Если выпал exception, то где-то сверху, где была создана транзакция ставится статус = “rollback”, - воркер подхватывает и отрабатывает зарегистрированные rollback методы в порядке приоритета.
Если транзакция висит долго (timeout), воркер сам переводит транзакцию в rollback.
Так же если система упала, то можно перед запуском все повисшие транзакции перевести в rollback.
Как то так…

Alen
естественно реплицированной 3 узла минимум
Эта рекомендация уже не так актуальна, т.к. журнал дает сопоставимую *sql'ям надежность в пределах одной ноды.

Офлайн

#9 Янв. 24, 2015 22:14:49

o7412369815963
От:
Зарегистрирован: 2009-06-17
Сообщения: 1986
Репутация: +  32  -
Профиль   Отправить e-mail  

События в транзакциях

Alen
Т.е. для каждой операции свой набор воркеров работающих независимо
Почему для каждой операции свои воркеры?
Мне кажется вариант, где все воркеры умеют выполнять любые операции, лучше. - просто “докидывать” один и тот же воркер на сервера если нужно больше производительности.

Офлайн

#10 Янв. 24, 2015 22:20:45

Alen
Зарегистрирован: 2013-08-01
Сообщения: 373
Репутация: +  49  -
Профиль   Отправить e-mail  

События в транзакциях

o7412369815963
Эта рекомендация уже не так актуальна, т.к. журнал дает сопоставимую *sql'ям надежность в пределах одной ноды.

Если хост в дауне, журнал не поможет.

o7412369815963
Почему для каждой операции свои воркеры?
Мне кажется вариант, где все воркеры умеют выполнять любые операции, лучше. - просто “докидывать” один и тот же воркер на сервера если нужно больше производительности.

Да, вы правы, имеет смысл если маршрут задач постоянен.

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version