Репликация и кэширование

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

Репликация

✏️ Репликация (англ. replication) — это создание и поддержание копий базы данных на нескольких серверах.
Существует два основных типа репликации: master-slave и multi-master.

Репликация master-slave

В модели master-slave, мастер-слейв есть:
  • Главный, первичный узел (master), ответственный за обработку всех операций записи и управление данными.
  • Подчинённый, вторичный узел, или реплика, слейв (англ. slave). Таких узлов может быть несколько. Они пассивно реплицируют данные от главного узла и обслуживают запросы на чтение в случае применения паттерна read-replica.
Когда на главном узле происходит операция записи, он регистрирует изменения в журнале транзакций. Затем ведомые узлы извлекают эти журналы и применяют изменения к своим копиям данных. В зависимости от требований к согласованности, ведомые узлы могут:
  • приостановить свою работу до получения обновлений от ведущего;
  • продолжать обслуживать возможно устаревшие данные, одновременно применяя последние изменения в фоновом режиме.
В случае «потери» мастера, следующим мастером становится кто-то из подчинённых узлов, в зависимости от настройки.
Такое распределение рабочей нагрузки между несколькими узлами повышает производительность запросов и надёжность данных, а также минимизирует время простоя системы. В контексте баз данных репликация master-slave устраняет узкие места в производительности и обеспечивает доступность данных в условиях увеличения пользовательского трафика или сбоев оборудования. Ещё этот подход помогает применять паттерн read-replica — в случае явного перенаправления трафика на чтение с реплики. Это можно сделать как средствами настройки, так и программно на уровне сервиса.

Паттерн read-replica

Суть паттерна проста: в случае большой нагрузки на чтение мы намеренно читаем данные только с реплик, но запись всегда происходит только через мастера.
Рассмотрим эту схему на примере пользователя сайта, допустим, Алисы.
  1. Когда Алиса создаёт заказ на сайте «Мегашоп», запрос отправляется в службу заказов.
  2. Служба заказов создаёт запись о заказе на главном узле — это операция записи. Данные реплицируются в два подчинённых узла.
  3. Алиса просматривает детали заказа. Данные считываются из подчинённого узла.
  4. Алиса просматривает историю последних заказов. Данные для чтения передаются из подчинённого узла.
В этой конфигурации существует серьёзная проблема — задержка репликации.
Иногда данные в репликах могут отставать на несколько секунд или даже минут. Это может произойти из-за задержки в сети или перегрузки сервера.
Если Алиса проверит статус заказа сразу после его размещения, она может не увидеть его, что вызовет путаницу. В таких случаях необходима последовательность «чтение после записи».
Возможные решения для устранения этой проблемы:
  • считывания с учётом задержки отправляются в основную базу данных;
  • чтения, за которыми сразу следуют записи, направляются в основную базу данных;
  • реляционная база данных обычно предоставляет способ проверить, совпадает ли реплика с первичной: если данные актуальны, она запросит реплику, а в противном случае завершит запрос на чтение ошибкой или прочитает данные с первичной базы.

Репликация multi-master

Multi-master, мульти-мастер — это тип репликации данных, при котором несколько узлов выполняют роль главных, то есть мастеров.
Данные синхронизируются между узлами, а запись может происходить на любом из мастер-узлов. В результате создаётся несколько копий данных. Система решает проблему конфликтов между одновременными изменениями.
Преимущества репликации multi-master
  • В случае сбоя одного главного узла другой главный узел может обновить и вставить данные.
  • Главные узлы находятся в разных местах, поэтому вероятность сбоя всех главных узлов крайне мала.
  • Обновления данных возможны на нескольких серверах.
  • Приложению не нужно направлять трафик только на один главный узел.
Недостатки репликации multi-master
  • Сложность настройки и поддержки.
  • Потенциальные задержки в данных.
Обычно такую репликацию реализуют, например, для поддержания горячей резервной копии всех сервисов в другом ЦОДе, сохраняя в самом ЦОДе репликацию master-slave.

Преимущества и недостатки репликации

У репликации в целом, вне зависимости от выбранного типа, есть преимущества и ограничения. Их нужно учитывать в тот момент, когда встаёт вопрос о внедрении репликации для масштабирования системы.

Преимущества репликации

  • Высокая доступность данных Данные дублируются на нескольких серверах, поэтому в случае выхода из строя одного сервера остальные продолжают обслуживать запросы, обеспечивая непрерывность работы системы.
  • Высокая производительность системы Нагрузку на чтение можно распределить между несколькими репликами, что снижает нагрузку на основной сервер (мастер) и улучшает производительность.
  • Отказоустойчивость (reliability) При сбое одного из серверов данные остаются доступными на других репликах, что минимизирует риск потери данных и простоев.
  • Гибкость в распределении нагрузки Запросы на чтение можно будет отправлять в реплику, которая ближе всего к пользователю географически. Это снижает задержки и повысит скорость доступа к данным. Такая гибкость особенно важна в распределённых системах с географически разнесёнными серверами.

Ограничения репликации

  • Сложности с консистентностью данных
    В случае задержек репликации данные на репликах могут быть устаревшими, что требует дополнительных механизмов синхронизации и управления конфликтами.
    Пример: допустим, у нас есть три сервера в кластере: сервер A (мастер), сервер B (реплика) и сервер C (реплика). Мы решили внедрить репликацию для повышения доступности и производительности системы. Сервер A является мастером и обрабатывает все запросы на запись, а серверы B и C являются репликами и обслуживают запросы на чтение. В случае задержек репликации данные на серверах B и C могут быть устаревшими.
    Если клиент обновляет информацию о своём заказе на сервере A, но запрос на чтение направляется на сервер B или C до завершения репликации, клиент увидит устаревшие данные. Это может вызвать путаницу и проблемы с данными, что требует дополнительных механизмов для синхронизации и управления конфликтами.
  • Ресурсозатратность
    Поддержание нескольких копий данных требует дополнительных вычислительных и дисковых ресурсов. Это увеличивает затраты на инфраструктуру и администрирование, так как каждый сервер должен иметь достаточную ёмкость для хранения всех данных.
    Пример: если база данных занимает 1 ТБ, то три сервера в кластере потребуют 3 ТБ суммарного дискового пространства. Кроме того, каждая репликация данных потребляет сетевые ресурсы и процессорное время.
  • Сложность управления
    Управление системой с несколькими репликами усложняется необходимостью мониторинга состояния каждой реплики, обеспечения их синхронизации и обработки сбоев. Администраторам необходимо следить за состоянием каждой реплики, проводить регулярные проверки их синхронизации и быстро реагировать на сбои.
    Пример: если сервер C выходит из строя, администраторы должны быстро восстановить его, чтобы он снова мог начать получать данные от мастера (сервера A). Такое важно быстро отслеживать, то есть потребуется настроить тщательный мониторинг.
Далее расскажем о критериях, на которые следует ориентироваться при выборе этого способа масштабирования.

Критерии для оценки целесообразности репликации

Репликация обеспечивает высокую доступность, повышенную производительность и отказоустойчивость и поэтому является весьма популярной и эффективной. Однако её внедрение требует тщательного планирования и управления для обеспечения консистентности данных и эффективного распределения нагрузки.
Для оценки целесообразности репликации нужно проанализировать требования к доступности, нагрузке на чтение, географическому распределению пользователей и критичности данных.
Например, вы понимаете, что цены в магазине должны быть всегда актуальными: данные критичные, доступность должна быть 99.95, а сейчас у вас и задержка в ценах до 5 минут, и база периодически падает на 1-2 часа из-за нагрузки.
Вот какими критериями можно оперировать:
  1. Требования к доступности
    Если система требует высокой доступности данных и минимизации простоев, репликация является подходящим решением. Она обеспечивает непрерывность работы даже при сбоях отдельных серверов.
  2. Нагрузка на чтение
    В системах с высокой нагрузкой на чтение репликация помогает распределить запросы на чтение между несколькими серверами, снижая нагрузку на основной сервер и улучшая производительность.
  3. Географическое распределение пользователей
    В системах с пользователями, распределёнными по различным географическим регионам, репликация позволяет направлять запросы на ближайшие реплики, что снижает задержки и улучшает пользовательский опыт.
  4. Критичность данных
    Для систем, где потеря данных недопустима, репликация обеспечивает дополнительный уровень защиты за счёт дублирования данных на нескольких серверах.
Закрепим знания несколькими короткими заданиями.

Задание 1

Пользователь оформил заказ на сайте интернет-магазина. Какой узел обработает запрос на чтение деталей заказа в конфигурации мастер-слейв репликации?
В конфигурации мастер-слейв репликации есть только один главный узел (мастер). Запрос на чтение деталей заказа будет обработан одним из подчинённых узлов (слейв), которые пассивно реплицируют данные от главного узла.

Задание 2

Выберите верные утверждения о преимуществах и ограничениях репликации данных.
За счёт распределения нагрузки на чтение между несколькими репликами происходит снижение нагрузки на основной сервер (мастер). Это улучшает производительность приложения.
Обеспечение консистентности данных между мастером и репликами — ограничение репликации. Оно приводит к тому, что данные на подчинённых узлах могут быть устаревшими.
Репликация требует мониторинга состояния каждой реплики для синхронизации данных и устранения сбоев — это ограничение репликации.
При выходе из строя одного сервера пользователи могут продолжать работать с приложением. Репликация повышает доступность приложения — это её преимущество.
Хранение данных на нескольких серверах снижает риск их потери. Это обеспечивает отказоустойчивость приложения.

Задание 3

В каких ситуациях целесообразно использовать репликацию?
Внутренняя система с небольшим количеством пользователей. Данные в неё сгружаются периодически из других систем. По этим данным пользователи смотрят отчёты. Данные можно перезалить в случае потери.
нецелесообразно
Работоспособность системы некритична, и нет риска потери данных: их можно перезалить.
База популярного сервиса учитывает продажи на сайте и финансовые операции.
целесообразно
Целесообразно по причине критичности и важности данных: потерять финансовые операции может быть весьма болезненно для организации.
В базу собираются данные за последние 10 лет о погодных условиях с метеостанций, расположенных в разных регионах страны. На их основе делаются прогнозы погоды для пользователей приложения бронирования отелей.
нецелесообразно
Показать пользователю приложения прогноз погоды — не ключевая функциональность приложения. Это говорит нам, что метеостанции вряд ли в собственности данного сервиса. А значит, потеря данных даже за большой период не вызовет проблем: можно взять данные у другого сервиса.
В базу собираются данные о температуре с разных метеостанций. На их основе делаются прогнозы для научного эксперимента.
целесообразно
Если данные используются для последующего научного эксперимента, то их потеря может быть весьма болезненной.
Обобщим все преимущества и ограничения репликации в таблице, чтобы вы могли возвращаться к ней, когда встанет вопрос о масштабировании.
Преимущества и ограничения репликации
ПреимуществаОграничения
Высокая доступность данныхСложности с консистентностью данных
Высокая производительность системыРесурсозатратность
ОтказоустойчивостьСложность управления
Гибкость в распределении нагрузки

Реализация репликации на базе MongoDB

В облаке репликация чаще всего доступна сразу из коробки. Например, в Яндекс Облаке управляемый сервис для MongoDB поддерживает репликацию по умолчанию: если в кластере несколько активных хостов, они автоматически выбирают основную реплику для обработки запросов на запись.
Подробнее о репликации и отказоустойчивости MongoDB можно прочитать в документации.
На отдельных серверах придётся настраивать это вручную — давайте разберёмся, как это сделать.
MongoDB поддерживает два типа репликации:
  • Replicaset Механизм работы Replicaset подобен multi-master, но затраты на поддержание берёт на себя полностью СУБД. Replicaset обеспечивает высокую доступность и горизонтальное масштабирование. В реплике каждый узел может выполнять операции чтения и записи, что позволяет распределять нагрузку и поддерживать постоянную доступность данных.
  • Master-slave  Этот тип репликации был доступен до версии 3.6 и предлагал более простую настройку, но имел ограничения в плане доступности и масштабирования.
💡 Replicaset — рекомендуемый разработчиками тип репликации на текущий момент.

Как работает репликация в MongoDB

  • Запись и чтение с основного сервера Драйвер клиентского приложения выполняет операции чтения и записи на основном узле, в MongoDB его называют primary node. Затем информация, записанная на primary, асинхронно копируется на вторичный узел — secondary node, или слейв.
  • Чтение с реплики Драйвер может считывать данные с secondary-нод, что позволяет уменьшить нагрузку на основной сервер (тот самый подход read-replica).
💡 Чтобы обеспечить доступность данных, важно помнить, что запись в MongoDB происходит асинхронно и данные могут быть доступны на secondary-нодах с задержкой. При сбое основного сервера запускается процесс выборов (кворум), чтобы определить новый primary.
В MongoDB можно настроить репликацию, указав параметры в строке подключения драйвера и используя специальные запросы для чтения данных с определённых узлов. Разберём это подробнее на примерах дальше в уроке. Чтобы обеспечить согласованность и надёжность при репликации, MongoDB применяет двухфазный протокол фиксации.
Первичный сервер отправляет сообщение о предстоящей операции записи всем вторичным серверам. После подтверждения готовности от вторичных серверов первичный сервер выполняет операцию и рассылает сообщение о фиксации.
Если какой-либо из вторичных серверов не подтверждает сообщение о фиксации, первичный сервер откатывает операцию, чтобы сохранить целостность данных во всём наборе реплик.
Кроме того, MongoDB использует сообщения heartbeat для отслеживания состояния серверов, автоматического обнаружения сбоев и восстановления после них.

Практика: настройте репликацию для MongoDB

Проще всего начать работу с MongoDB, используя Docker и Docker Compose:
Для этого посетите официальный веб-сайт Docker и загрузите соответствующую версию Docker для вашей операционной системы. Docker Compose включён в установку Docker Desktop в Windows и macOS. Для пользователей Linux следуйте инструкциям на официальном веб-сайте Docker Compose.
После установки нужно создать файл docker-compose.yaml:
YAML
version: '3'
services:
  mongodb1:
    image: mongo:latest # docker образ
    container_name: mongodb1
    restart: always
    ports:
      - "27017:27017"
    networks:
      app-network:
        ipv4_address: 173.17.0.10
    volumes:
      - mongodb1-data:/data/db
    command:
      [
        "--replSet",
        "rs0",
        "--bind_ip_all",
        "--port",
        "27017"
      ] #команда для создания реплики
    healthcheck:
      test: [ "CMD", "mongo", "--eval", "db.adminCommand('ping')" ]
      interval: 5s
      start_period: 10s

  mongodb2:
    image: mongo:latest
    container_name: mongodb2
    restart: always
    ports:
      - "27018:27018"
    networks:
      app-network:
        ipv4_address: 173.17.0.9
    volumes:
      - mongodb2-data:/data/db
    command:
      [
        "--replSet",
        "rs0",
        "--bind_ip_all",
        "--port",
        "27018"
      ]
    healthcheck:
      test: [ "CMD", "mongo", "--eval", "db.adminCommand('ping')" ]
      interval: 5s
      start_period: 10s

  mongodb3:
    image: mongo:latest
    container_name: mongodb3
    restart: always
    ports:
      - "27019:27019"
    networks:
      app-network:
        ipv4_address: 173.17.0.8
    volumes:
      - mongodb3-data:/data/db
    command:
      [
        "--replSet",
        "rs0",
        "--bind_ip_all",
        "--port",
        "27019"
      ]
    healthcheck:
      test: [ "CMD", "mongo", "--eval", "db.adminCommand('ping')" ]
      interval: 5s
      start_period: 10s

networks:
  app-network:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 173.17.0.0/16

volumes:
  mongodb1-data:
  mongodb2-data:
  mongodb3-data: 
В файле docker-compose мы определили три контейнера MongoDB, каждый из которых представляет узел в наборе реплик. Флаг --replSet устанавливает имя набора реплик равным "rs0" и, собственно, запускает Mongo в режиме репликации, а флаг --bind_ip_all разрешает подключения со всех сетевых интерфейсов.
Запускаем:
BASH
docker-compose up -d  
Подключаемся к любому контейнеру:
BASH
docker exec -it mongodb1 mongosh 
Создаём набор реплик в командной оболочке mongosh:
JSX
> rs.initiate({_id: "rs0", members: [
{_id: 0, host: "mongodb1:27017"},
{_id: 1, host: "mongodb2:27018"},
{_id: 2, host: "mongodb3:27019"}
]}) 
В результате вы получите:
С репликацией закончили. Пора рассмотреть другой метод горизонтального масштабирования — кэширование.

Кэширование

Принцип работы кэширования, или паттерна Cache Aside, выглядит следующим образом:
  1. Приложение проверяет наличие нужных данных в кэше.
  2. Если данных там нет, то запрос направляется в хранилище.
  3. На обратном пути данные передаются в кэш, а запрос возвращается пользователю.
☝ Кэширование снижает нагрузку при большом количестве операций чтения одинаковых данных.
Когда использовать кэширование
  • При высокой нагрузке на чтение для текущих ресурсов Определить, является ли нагрузка высокой, можно, посмотрев на графики утилизации процессора, памяти, дисков. Использование кэширования при низких нагрузках только усложнит систему.
  • При наличии редко изменяемой информации, которую необходимо часто получать из хранилища На практике получение такой информации занимает от минуты и дольше. Это могут быть предпочтения пользователя, статический контент. Если информация постоянно меняется, то преимущество кэширование будет «съедено» затратами на поддержание актуальности контента в кэше.
💡 При работе с кэшированием есть и сложность: данными в кэше нужно управлять, чтобы поддерживать их согласованность.
Далее мы расскажем, как настроить кэширование с помощью Redis, а потом вы сделаете это на практике.

Redis Cluster для кэширования данных

Redis — один из популярных и стабильных сервисов для кэширования. Он позволяет реплицировать и шардировать данные — разбивать на сегменты.
Механизм работы Redis Cluster основан на распределённом кэше.
✏️ Распределённый кэш — это система, в которой данные хранятся на нескольких узлах кластера и в нескольких кластерах в разных центрах обработки данных по всему миру.
Система распределённого кэша объединяет оперативную память нескольких сетевых компьютеров в единое хранилище данных в оперативной памяти, которое используется в качестве кэша для быстрого доступа к данным.
Такие системы особенно полезны для больших объёмов данных и высоких нагрузок. Они позволяют постепенно расширять и масштабировать систему, добавляя новые компьютеры в кластер. Такой кэш помогает снизить нагрузку на БД и повысить отказоустойчивость.
В предыдущий docker-compose файл добавьте конфигурацию:
YAML
 redis_1:
    image: "redis:latest"
    container_name: redis_1
    ports:
      - "6379"
    volumes:
      - redis_1_data:/data
      - ./redis/redis.conf:/usr/local/etc/redis/redis.conf
    command: [ "redis-server", "/usr/local/etc/redis/redis.conf" ]
    networks:
      app-network:
        ipv4_address: 173.17.0.2

  redis_2:
    image: "redis:latest"
    container_name: redis_2
    ports:
      - "6379"
    volumes:
      - redis_2_data:/data
      - ./redis/redis.conf:/usr/local/etc/redis/redis.conf
    command: [ "redis-server", "/usr/local/etc/redis/redis.conf" ]
    networks:
      app-network:
        ipv4_address: 173.17.0.3

  redis_3:
    image: "redis:latest"
    container_name: redis_3
    ports:
      - "6379"
    volumes:
      - redis_3_data:/data
      - ./redis/redis.conf:/usr/local/etc/redis/redis.conf
    command: [ "redis-server", "/usr/local/etc/redis/redis.conf" ]
    networks:
      app-network:
        ipv4_address: 173.17.0.4

  redis_4:
    image: "redis:latest"
    container_name: redis_4
    ports:
      - "6379"
    volumes:
      - redis_4_data:/data
      - ./redis/redis.conf:/usr/local/etc/redis/redis.conf
    command: [ "redis-server", "/usr/local/etc/redis/redis.conf" ]
    networks:
      app-network:
        ipv4_address: 173.17.0.5

  redis_5:
    image: "redis:latest"
    container_name: redis_5
    ports:
      - "6379"
    volumes:
      - redis_5_data:/data
      - ./redis/redis.conf:/usr/local/etc/redis/redis.conf
    command: [ "redis-server", "/usr/local/etc/redis/redis.conf" ]
    networks:
      app-network:
        ipv4_address: 173.17.0.6

  redis_6:
    image: "redis:latest"
    container_name: redis_6
    ports:
      - "6379"
    volumes:
      - redis_6_data:/data
      - ./redis/redis.conf:/usr/local/etc/redis/redis.conf
    command: [ "redis-server", "/usr/local/etc/redis/redis.conf" ]
    networks:
      app-network:
        ipv4_address: 173.17.0.7

volumes:
  redis_1_data: {}
  redis_2_data: {}
  redis_3_data: {}
  redis_4_data: {}
  redis_5_data: {}
  redis_6_data: {} 
Прежде чем продолжить практику, расскажем механизм работы кластера Redis.

Механизм работы Redis

Этот кластер состоит из трёх сегментов: это минимальное количество сегментов для осуществления кэширования в Redis. У каждого сегмента есть главный узел (master), который отвечает за все операции записи, а также узел-реплика (slave), который хранит копию данных. Сегмент кластера Redis может содержать до 500 реплик — так устроено в AWS и зависит от провайдера.
Посмотрите на схему работы кэширования в Redis:
Клиенты выполняют операции чтения и записи с узлами M1, M2, M3 и только чтения с S1, S2, S3. Между ведущими и подчинёнными узлами выполняется репликация данных. Для определения общего состояния кластера используется протокол gossip.

Дальнейшие настройки

В конфигурации присутствует ./redis/redis.conf для настройки Redis’а:
BASH
port 6379
cluster-enabled yes #активация кластерного режима
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
 
Запускаем:
BASH
docker-compose up -d 
Подключаемся к любой ноде и выполняем команду для создания кластера:
BASH
docker exec -it redis_1
echo "yes" | redis-cli --cluster create   173.17.0.2:6379   173.17.0.3:6379   173.17.0.4:6379   173.17.0.5:6379   173.17.0.6:6379   173.17.0.7:6379   --cluster-replicas 1 
cluster-replicas 1 как раз говорит о том, что у каждого мастера должно быть по одной реплике.
Результат:
Также можно выполнить команду для получения информации о кластере:
JSX
redis-cli cluster nodes  
Вот вы и подняли распределённый кэш на примере Redis.
Полный docker-compose и redis.conf: https://github.com/db-exp/redis-mongo
Вы настроили кэширование. Дальнейшее улучшение метрик возможно уже доработками кода.

Как сделать ещё лучше

Приведём пример улучшения кода на Typescript и Node.js:
JSX
> mkdir nodejs-api
> cd nodejs-api
> npm init -y
> npm install express mongoose redis
> touch index.js

const express = require('express');
const redis = require('redis');
const app = express();
const PORT = 3000;

const client = redis.createClient();

// работа Redis - достаём данные, если они есть по ссылке /api/products
const cache = (req, res, next) => {
  const cacheKey = req.originalUrl;
  client.get(cacheKey, (err, data) => {
    if (err) throw err;
    if (data !== null) {
      res.json(JSON.parse(data));
    } else {
      next();
    }
  });
};

// сбрасываем кэш в случае обновления данных
const invalidateCache = (cacheKey) => {
  client.del(cacheKey, (err, response) => {
    if (err) throw err;
    console.log(`Cache key "${cacheKey}" invalidated`);
  });
};

app.get('/api/products', cache, (req, res) => {
  
  const products = //логика получения данных из MongoDB

  // Сохраняем данные по ключу /api/products на 1 минуту
  client.setex(req.originalUrl, 120, JSON.stringify(products));

  res.json(products);
});

// При обновлении данных - сбрасываем кэш
app.post('/api/products', (req, res) => {
  //обновляем данные в MongoDB
  
  invalidateCache('/api/products');

  res.json({ message: 'Product data updated successfully' });
});

app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}`);
});
 
При запросе мы либо достаём запись из Redis, либо вызываем логику получения из базы. В случае обновления данных — сбрасываем кэш.

Реализация репликации в различных БД

В этом уроке вы рассмотрели реализацию репликации и кэширования на примере MongoDB и Redis. Этот механизм можно настроить и для других баз данных — разберём это кратко.
Репликация присуща большинству инструментов работы с данными:
  • Базам, например, PostgreSQL, MySQL.
  • Инструментам кэширования, например Memcached.
В других базах данных свои реализации механизма репликации master-slave и multi-master. Многие облачные решения уже идут преднастроенными для репликации для повышения отказоустойчивости и распределения нагрузки.
Например, PostgreSQL использует потоковую или логическую репликации в рамках механизмов master-slave и multi-master.
  • Потоковая репликация
    Процесс копирования данных с основного сервера PostgreSQL на реплики. При этом используется WAL (журнал предзаписи транзакций), который позволяет восстановить данные в случае сбоя. Потоковая может быть синхронной или асинхронной.
    Для настройки потоковой репликации все серверы должны быть одной версии, работать на одной операционной системе и архитектуре.
  • Логическая репликация
    Возможность настройки логической репликации появилась в PostgreSQL 10. Отличается от потоковой тем, что она оперирует записями в таблицах PostgreSQL, а не физическим уровнем данных. 
    Этот вид репликации основан на механизме публикации/подписки: один сервер публикует изменения, а другой подписывается на них.

Задание 4

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

Итоги

  • Репликация (replication) — это создание и поддержание копий базы данных на нескольких серверах. Она бывает двух типов: мастер-слейв (master-slave) и мульти-мастер (multi-master). В первом случае главный сервер всегда один, а во втором их несколько. Выбор типа зависит от задачи и условий масштабирования.
  • В облаке репликация часто преднастроена, однако на отдельном сервере может понадобиться настраивать её самостоятельно. Вы научились делать это в MongoDB.
  • Кэширование — это ещё один метод горизонтального масштабирования, который позволяет сохранять часто используемые данные в кэш.
  • Redis — один из популярных и стабильных сервисов для кэширования. Он позволяет реплицировать и шардировать данные — разбивать на сегменты. Вы научились настраивать кэширование в Redis.
В следующем уроке вы узнаете больше о горизонтальном масштабировании приложений.

Что почитать про Redis

Подробная статья на Хабре с архитектурой Redis и принципами его работы

Курсы

Подробнее о курсе

Входной тест

Как всё устроено

Микрофронтенды и разбивка монолитной системы на микросервисы

Шардирование и репликация

Создание микросервисов, построение пайплайна CI/CD

Кеширование, построение мониторинга и адаптация к высокой нагрузке

Переход на Hybrid cloud и Multi-cloud, создание AI/ML чат-бота

Создание highload в realtime-среде

Переход на event-driven архитектуру, объединение сервисов через SSO

Как пройти аудит безопасности и соответствовать его требованиям

Работа с требованиями и стейкхолдерами

Соответствие продукта требованиям data privacy, планирование сложной миграции

Адаптация к большому объему данных, построение BI и создание технологического роадмапа для продукта

Завершающий модуль