Найти в Дзене
Одиночная палата

Begin /* Персистентность

Оглавление

Терминология

Persistence - один из айтишных терминов, который не переводится прямо на русский. Во всяком случае не одним словом. Сохраняемость? Персистентность - способность системы сохранять собственное состояние после остановки процесса. Вообще феномен присущ не только для информационных систем. Способность тритонов и прочих примитивных гадов "оживать" после полной заморозки, например - сходное явление. Другое дело, что нам пока не до конца известно, какая часть, если так можно выразиться, сознания, восстанавливается весной, после того как лягушка оттает и её сердце возобновит прокачку глюкозы к мозгу. Ей может быть не так много и надо.

Похожим образом это выглядит и в информационных системах. Не все монстры восстанавливаются в игре там, где они были в момент сохранения игры. Для экономии ресурсов состояние окружения сохраняется только для сущностей, прямо влияющих на дальнейший процесс. Даже если мы имеем дело с так называемой полной персистентностью, когда как будто бы в системе сохраняется полное состояние на каждый момент времени, в ней существуют неделимые изменения, состоящие на самом деле из нескольких операций. Эти изменения считаются логически связанными и позволяют сохранять консистентность - еще один термин, обозначающий в общем случае детерминированность автомата что в структурах данных не нарушена логика.

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

Цели

Персистентность как явление всегда связано с наличием в системе не всегда и не всем очевидного феномена как состояние. Относительно программирования можно определить данный феномен таким образом, что система имеет состояние когда функция имеет в качестве одной из параметров временную или пространственную характеристику - зависит от того когда и где эта функция была вызвана. Например, программа, функция, вычисления синуса не имеет состояния. В какой бы момент времени и при каком бы окружении вы не вызвали, её результат при одинаковом аргументе всегда ожидается одинаковым.

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

Менее очевидные примеры всегда так или иначе связаны с тем, что в системе не учтены такие параметры. И это, разумеется, не всегда только временная зона и локаль. Многие системы имеют собственные неявные состояния: остатки на счетах, наличие товаров, курсы валют, погодные условия. Мы не говорим здесь о состояниях, которые явным образом присутствуют в техническом задании и представляют из себя суть некоего процесса. Когда в условиях прямо говорится, что объект имеет энное количество состояний и имеется некий алгоритм перехода из одного состояния в другое, то предписание о том надо ли хранить и в каком объеме надо это делать обычно указано рядом. В стрелялке есть место сохранения и находящиеся рядом противники. В карточной игре - карты на руках у игроков и на столе.

Сложность в целеполагании возникает, когда не очень понятно из условий что и как надо хранить. Очевидно, что не нужно хранить промежуточные результаты алгоритма вычисления синуса угла. С другой стороны, если посмотреть на реализацию подавляющего большинства программ и функций в них, то оказывается, что программисты занимаются именно этим - пытаются запоминать действия не требующие никакой персистентности. В то же время, можно наблюдать случаи, когда при этом важная информация, действительно влияющая на состояние попросту проигнорирована. Это говорит о том, что достаточно часто программист просто не понимает что и зачем ему надо сохранять, и делает это интуитивно и лишь с целью перестраховаться. Надо сказать, что перестраховка это тоже полезная вещь и часто только поэтому не происходит ничего критического. Но это, понятно, не гарантия.

Как повелось

Исторически сложилось так, что в какой-то момент времени в качестве, если не единственного, то основного "разумного" средства хранения данных в программах стали использовать СУБД. Надо или не надо - поднимаем базу и пихаем в нее как можно больше подробных данных о процессе. И это в общем случае неплохое решение, если, разумеется, речь не идет об экономии ресурсов и скорости выполнения. Будем и этапы вычисления синусов хранить - ничего страшного.

Кратное усиление данной парадигмы произошло во время бурного цветения веб-сервисов и сценарного подхода к программированию - stateless протоколов. Надо хранить данные внутри сессии - передаем их взад-перед между клиентом и сервером. Данных слишком много что бы каждый раз передавать их по сетям - создаем идентификатор сессии и храним промежуточные данные в БД. В том числе и состояния объектов. В ногу с таким подходом развивались железо и СУБД, подпевая и пропагандируя поступать похожим образом в любой непонятной ситуации.

Всеобщее благоденствие начало сбоить когда наиболее крупным сервисам перестало хватать мощностей монолитных СУБД и комплексов оборудования, на которых они установлены. Пришлось выкручиваться двумя параллельными способами: строить распределенные высокопроизводительные системы хранения данных, и пересматривать подходы к программированию высоконагруженных сервисов. Передавать лишние данные по коммуникационным каналам или обращаться все время к дисковым базам данных стало не выгодно. В следствии глобализации и роста интернета постепенно тенденция скатилась и до не самых больших проектов. Нынче даже самый заурядный производитель не самых сложных приложений обязан думать о том, что его сервис может лавинообразно набрать клиентскую базу. И верхний потолок требований к производительности должен быть там, где экономия ресурсов отнюдь не последний аргумент.

В полный рост встал вопрос о том что и как нужно сохранять. Надо ли вообще что-то сохранять или можно обойтись без каких-либо хранилищ данных? Где та граница, когда мы обязаны пожертвовать производительностью в целях повысить надежность. Есть ли смысл хранить состояние процесса, если его можно вычислить заново? Известно, что тригонометрические функции вычисляются с применением приближения многочленами. Может быть имеет смысл хранить уже вычисленные значения отдельных членов ряда в базе данных, а потом, после восстановления, продолжить с места прерывания?

Как быть дальше?

Пример с синусом угла может быть не самый наглядный, но он имеет смысл в том ключе, что в жизни мы делаем некоторые исходные, вообще-то ничем не обоснованные, допущения. Очевидно, что сохранение промежуточных результатов вычисления в случае с синусом будет на порядки медленнее чем вычисление заново. Так ли это очевидно с другими функциями, особенно если рассматривать любую программу именно как некая абстрактная функция, каковой она и является. Какова выгода от того что мы сохраняем состояния? Может быть изначально нужно систему с наличием состояний делать не в виде stateless скрипта, а в виде постоянно запущенной программы? Как в таком случае защититься от сбоев? Сколько нужно времени программе на перезапуск? Может ли она восстановиться после сбоя быстрее, чем время требуемое на обработку потока запросов накопленных во время простоя?

На эти и многие другие похожие вопросы нынче приходится давать ответы прежде чем вообще что-либо реализовывать. Существуют на эти вопросы и типовые ответы. Когда-то можно кэшировать результаты наиболее частых запросов, не отказываясь от старой парадигмы. Во многих случаях можно воспользоваться той или иной стратегией хранения состояний не полностью в каждый момент времени, а путем регистрации изменений в некий периодический снапшот системы. Есть и третий, чуть реже используемый вариант - а зачем нам вообще что-то хранить? Должна ли система обладать персистентностью изначально? Формула: есть состояния - должна быть персистентность работает как оказывается не всегда. Если не сказать практически никогда.

Обидно, конечно, начинать уровень заново когда вот вот уже доскакал до флажка или перепечатывать умную статью после сбоя текстового редактора. Но согласимся, ведь автосохранение в текстовых редакторах это лишь дополнительная опция, а никак не требуемый функционал. Есть - хорошо. Нет? Будем сохраняться чуть чаще. Игра не обязательно гарантирует вам сохранение после прохождения чекпойнтов, и это прямо указано в условиях. То есть, если вы не подписались под тем, что бы ваша программа должна вообще что-то там сохранять и восстанавливать то это и не ваша обязанность и головная боль. Персистентность может быть обеспечена и клиентом. Информация о необходимых операциях может храниться как у самих клиентов, так и сохраняться на стороне программы исключительно по их требованию.

Бухгалтерия или даже банк сами по себе не обязаны ни перед кем хранить какое бы то ни было промежуточное состояние. Бухгалтерия, являясь функцией, выполняющей операции над счетами клиентов, может теоретически быть вся восстановлена по сохраненным у клиентов зарегистрированным требованиям до любого момента. Разумеется, будет странно, если перед каждым следующим действием бухгалтер будет рассчитывать остатки на счетах заново. Именно для этого существует так называемый операционный день, когда все операции предыдущего дня завершены и состояние всех счетов на момент начала текущего дня полностью известно и консистентно. Причем чем ближе к текущей операции сохраненное состояние, тем понятно бухгалтеру легче. Напрашивается вопрос, а почему бы не сделать вместо дня, скажем, операционный час, или минуту?

Между функцией вычисления синуса и проведения операции в бухгалтерии существует некий "понятный" переход, когда персистентность нам все еще не нужна и уже наверное лучше пусть будет. А вот где именно этот переход находится на самом то деле зависит сугубо от договоренности, а вовсе ни из каких-то формальных признаков. Формальные признаки, как то производительность, надежность, доступность являются лишь причинами, на основании которых эти договоренности могут быть пересмотрены.

Трейдоффы

Еще один новомодный термин без которого сложно объяснить что же получается по итогу. Trade-off в отличии от compromise больше связан именно с торгом. Причем торгом не с собственной совестью и не между заказчиком и исполнителем. Трейдоффы дилеммы между персистентностью и не персистентностью лежат где-то на уровне архитектуры информационной системы и дизайна конкретной реализации проекта. Техническое задание может не определять вам конкретные границы и объемы хранимых состояний. Оно в общем и не должно содержать таких указаний. Указания о применяемой стратегии должны исходить из следующего шага при решении вопроса о том как уместить реализацию в требования. А вот требования как-раз могут и должны указывать на разнообразные прогнозируемые количественные характеристики.

Для программиста реализация той или иной модели персистентности сопровождается вполне осязаемыми и исчислимыми сложностями. От самого простого - не хранить нигде ничего, до реализации распределенного разделяемого транзакционного хранилища вручную. Поэтому торговаться в данном случае нужно с архитекторами, с теми кто выполняет декомпозицию высокого уровня. Со стороны архитектора может показаться, что нужна убер надежная, при этом самая быстрая и полная стратегия. И если нет сопротивления со стороны того кто все это будет реализовать, то непременно так оно и получится. За исключением, конечно тех случаев, когда и архитектор и исполнитель одно и то же лицо. Но и в этом случае надо попытаться максимально раздвоить личность и посмотреть на проблему с обоих позиций.

А вот архитектор, если он согласен с доводами программистов, в свою очередь может повлиять и на уровень требований в техническом задании к проекту. У заказчика уж тем более нет цели облегчить работу исполнителям, поэтому требования всегда будут подразумевать максимальный вариант. Четырехколесный велосипед с ремнями безопасности и системой катапультирования это не такое уж и утрированное описание стандартного технического задания. Может быть, в те далекие времена, когда перезагрузить сервер считалось профилактической мерой, а резервные копии писались на магнитные ленты, имело смысл делать что-то на всякий случай. Нынче же представить, что ваша программа на серьезном хостинге "упадет" из-за внешних причин, довольно сложно. Должно произойти нечто настолько масштабное, что ваша проблема при этом окажется не такой уж и значительной. Настало время пересмотреть и походы.

Вместе с глобальной цифровизацией общества, с распространением средств доступа к цифровым услугам, с увеличением ширины каналов связи, и вместе с тем с достижением физических пределов производительности отдельных элементов обслуживающего оборудования, востребованность к максимально сбалансированным информационным системам будет только расти. Не предвидится такого момента, когда вновь программисты смогут действовать в любой ситуации по какому-то универсальному шаблону. А задача балансировки между избыточной сложностью и лишними необоснованными требованиями не должна оставаться вотчиной некоего ультимативного звена - архитектора или менеджера. Не только лишь все, вернее не мало кто еще должен смотреть в завтрашний день. В том числе и каждый программист.

*/

End;