avlasov (avlasov) wrote,
avlasov
avlasov

Category:

Мини-учебнег по распределенным системам/протоколам. Репликация, дублирование и веб-системы

Будем различать дублирование и репликацию. Для устранения SPOF или для увеличения производительности мы можем дублировать устройства и/или процессы, т.е. какие-то типы запросов могут обрабатывать разные дивайсы. Точно также мы можем делать копии данных, как с целью устранения SPOF так и увеличения производительности. Дублирование данных назовем репликацией. Будем различать горизонтальную и вертикальную репликацию. Горизонтальная - это когда мы делаем однородные копии, ну например записываем данные на несколько дисков, или в память нескольких процессов. А вертикальная - это копии данных на разных типах носителей, например, кэш - это копия данных, которые храняться, положим на диске (или в удаленной или в более медленной памяти). Бэкап - тоже пример вертикальной репликации.

Важно понимать взаимосвязи между репликами данных, а также между дублированием устройств/процессов и репликами данных. Тут могут быть разные схемы взаимодействия. Например, мы храним данные на диске, но диск может отказать. Значит надо дублировать данные на два и более диска - "зеркало". Однако, если два диска в одном компе и он откажет, то остальные процессы в системе не смогут получить доступ к данным - исключая случай когда диск подключен к SAN, т.е. фактически доступ к диску дублирован. Таким образом, для отказоустойчивого персистенса нам нужно не только писать данные на несколько дисков, но и обеспечить дублирование для доступа к этим дискам. Один из способов - специальная дисковая сеть (SAN). Более простой и доступный - дублировать данные на диски, расположенные на разных компьютерах в сети. Отмечу, что зеркало, т.е. RAID 1 на самом деле не предназначен для сохранения данных от сбоя, по крайней мере, этого недостаточно (коррелированные сбои и все такое). Для предохранения данных от потери нужно делать бэкапы, ну и вообще держать минимум три копии данных. Ведь если у нас один диск отвалися, то пока мы копируем данные со второго диска на третий, у нас может порости и первый диск - у современных дисков такой большой объем, что вероятностью сбоя во время копирования не стоит пренебрегать. Именно поэтому, нужно минимум трехкратное резервирование и лучше на разнородных носителях, чтобы избежать коррелированных сбоев.

Итого, нам нужно делать бэкап, а также зачастую дублирование дисков для маскировки сбоев в составе работающей системы. При этом нередко, копии держат на разных компьютерах, но точно так же, может применяться дублирование и в одном компе (RAID 1).

Далее, допустим мы держим данные в оперативной памяти (но не храним на диске, или записываем с задержкой). Вероятность сбоя компа выше чем вероятность сбоя диска, так что данные можно легко потерять. Чтобы этого избежать, можно реплицировать данные, т.е. хранить копию на нескольких компах (двух или более), это позволяет избежать того или иного кол-ва сбоев. Конечно, несколько компов тоже могут выйти из строя, так что это менее надежная схема нежели диск, но зато более быстрая, так что ее тоже вполне можно применять.

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

Далее, для ускорения производительности мы можем как дублировать дивайсы/процессы, так и делать репликацию данных, как горизонтальную (собственно репликация), так и вертикальную (кэширование). Например, мы сделали несколько копий процессов веб-сервера и раскидываем запросы от клиентов по ним. Процессы могут не хранить состояние, а лазить за ним на какой-то shared процесс, котрый хранит состояние (DB, App server, MemCache, etc) - stateless архитектура. Т.е. здесь у нас только дублирование дивайстов/процессов. Хотя если мы делаем кэширование - то тут у нас есть (вертикальная) репликация: мы держим основных копии данных в кэше.
В случае Stateful архитектуры у нас тоже может не быть горизонтальной репликации, например, мы можем хранить пользовательские сессии на разных процессах и перенаправлять запросы к ним. Точно так же, мы можем держать общее состояние системы на каком-то процессе (App Server, DB Server) и перенаправлять туда запросы/выполнять RPC. Но зачастую состояние в Stateful архитектуре есть копия основного состояния в DB, т.е. нам нужно поддерживать согласованность этих реплик в той или иной степени.
В случае Stateful мы также можем использовать горизонтальную репликацию данных, т.е. держать копии одних и тех же данных на нескольких серверах. Таким образом, сервера могут параллельно исполнять запросы к одним и тем же данным, что может быть нужно как для обеспечения отказоустойчивости, так и производительности данных.

Особую роль репликация играет для данных уровня приложения, для DB и для кэшей. Ведь эти компоненты используются разными процессами, в том числе stateless, и если их не реплицировать, они являются очевидными SPOF. Так что в полноценной отказоустойчивой системе нам нужно уметь дублировать функционал DB, application состояния, а также распределенных кэшей.

Отмечу, что это еще не все. Ведь веб-сервер пользователи видят через доменное имя и IP адрес(адреса). IP адрес тоже может отвалиться - стать недоступным из-за сбоя сетевой инфраструктуры. Точно так же, для увеличения производительности мы можем обслуживать запросы от разных клиентов через разные IP адреса, и разные доменные имена. Например, мы можем завести несколько сервером для статического контента, типа static1, static2, etc. И выдавать разным пользователям разные имена. Итого, видно, что дублирование применяется на многих уровнях. Перечислим (неполный) список:
1 диски
2 бэкап (разнородные носители информации)
3 оперативная память
4 компьютеры
5 источники питания
6 сетевые карты и маршрутизаторы
7 IP адреса
8 доменные имена
9 процессы и сервисы

Чтобы воспользоваться дублированием для повышения производительности, нам нужно уметь делать load-balancing, т.е. перенаправлять запросы на разные обслуживающие дивайсы/процессы. Точно так же, чтобы получить отказоустойчивость, нам нужно уметь детектировать сбои и перенаправлять запросы на дублирующие сервисы/реплики. Обычно надо совмещать load-balancing с обработкой сбоев, ведь если мы знаем, что какой-то сервак не работает, то и нет смысла перекидывать на него запросы. Ну и часто (но не всегда), если у нас есть какие-то резервные дивайсы, то мы можем их использовать для load-balanсing'а, что обычно называется Active/Active репликацией или Master/Master. В то же время, дублирующее устройство может находиться в режиме ожидания или ограниченной функциональности (например, исполнять только запросы на чтение).

Вобщем, в случае распределенных веб-систем, у нас примерно та же картина, что и в случае распределеных систем вообще, но есть своя специфика - клиенты получают доступ через HTTP, доменные имена и IP адреса. Так что дублирование имеет свою специфику (иногда весьма и весьма непросто реализуемую).
В следующем посте мы подробнее разберемся с понятием состояния. Ибо ведь его и нужно реплицировать, хотя иногда не нужно. Вот чтобы понять когда нужно, а когда нет, и какие нам нужны гарантии согласованности, нужно сперва разобраться с тем какого вида бывает состояние.
Subscribe
  • Post a new comment

    Error

    default userpic

    Your reply will be screened

    When you submit the form an invisible reCAPTCHA check will be performed.
    You must follow the Privacy Policy and Google Terms of use.
  • 0 comments