Calvin Protocol для распределенных транзакций
Многие знают про протокол двухфазной фиксации (2PC), но мало кто слышал про протокол Calvin. Честно говоря, до недавних пор я тоже относился к этому меньшинству, поэтому решил поделиться своей находкой с вами. Однако для начала предлагаю освежить память.
Распределенная транзакция - это транзакция, затрагивающая несколько ресурсов распределенной системы. Как и обычные транзакции в монолитных базах данных, распределенные действуют по принципу "всё или ничего". Тематика достаточно стара, хорошо проработана, отражена в стандарте X/Open XA (1991), который реализован на многих платформах. Таким образом, концепция распределенных транзакций появилась задолго до появления шумихи вокруг микросервисов, но сейчас особенно актуальна и рассматривается как возможный инструмент обеспечения согласованности данных.
Протокол двухфазной фиксации (2PC) часто рассматривается как синоним реализации распределенных транзакций. До недавних пор это было вполне справедливо, но на самом деле эти термины не являются синонимами. Главными преимуществами 2PC является его прикладная универсальность и относительная простота реализации. Главными недостатками 2PC являются длительные блокировки, неустойчивость к сбоям, отсутствие изоляции. Вместе с этим блокировки все-таки локальны по отношению к ресурсу и не мешают конкурентному выполнению транзакций (в отличие от Calvin).
В 2012 была опубликована статья "Calvin: Fast Distributed Transactions for Partitioned Database Systems" с описанием нового подхода к реализации распределенных транзакций. В его основу положена идея формирования журнала транзакций и подачи его на вход исполнителю, вместо того чтобы позволить ему самому формировать журнал. (Под исполнителем понимается какой-то ресурс, например, реплика базы данных.) Такой подход позволяет уменьшить число сетевых взаимодействий, обеспечив высокую скорость выполнения распределенных транзакций.
😀 Подход был назван не в честь производителя трусов, как можно было бы подумать изначально, а в честь французского богослова Жана Кальвина (Jean Calvin), считавшего, что все события человеческой жизни предопределены Богом. Ведь если журнал сформирован заранее, то и результат исполнения транзакций из этого журнала предопределён.
Calvin обеспечивает порядок выполнения транзакций, назначая каждой порядковый номер. Иначе говоря, имеется виртуальная глобальная очередь, которая формируется до того, как исполнители начнут обрабатывать транзакции. Будучи упорядоченными, транзакции всегда получают необходимые блокировки в одном и том же порядке. Благодаря строгому и предопределенному порядку следований транзакций и блокировок гарантируется итоговая согласованность исполнителей.
Таким образом, можно обозначить следующие особенности подхода:
- Один и тот же журнал можно подавать на вход любому количеству исполнителей.
- Если исполнитель записал транзакцию в свой журнал, значит, эта транзакция выполнена.
- Если одна транзакция останавливается в ожидании доступа к диску, все остальные транзакции тоже ждут!
Несомненным достоинством Calvin является практически неограниченная возможность горизонтального масштабирования с сохранением ACID-гарантий. Причём гарантии обеспечиваются даже в случаях, когда транзакция охватывает несколько распределенных партиций.
Между тем, система хорошо масштабируется только в том случае, если разные приложения работают с разными данными. При наличии записей, за которые идёт высокая конкуренция, возможен резкий рост накладных расходов на повторное планирование транзакций.
Резонный вопрос: есть ли практические реализации и опыт использования этого подхода? Да, есть. Например, разработчики Apache Cassandra разрабатывают совместимый продукт под названием Accord. Он должен позволить выполнять запросы к Cassandra, объединяя их в ACID-транзакции. Однако гораздо больших успехов добились разработчики YDB, о чём можно почитать в их официальном блоге.
P.s. Жду от вас историй про опыт работы с распределёнными транзакциями или YDB. ;-)
P.p.s. Если вам интересна данная тематика, присоединяйтесь к моей новостной ленте в Telegram или здесь. Буду рад поделиться опытом. ;-)