Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

"Кластеры баз данных: делаем сложные вещи просто" Андрей Тихонов (Avito)

1,146 views

Published on

Порой в процессе развития высоконагруженного проекта наступает момент, когда необходимо масштабирование. Возможно, ваш проект впервые упёрся в производительность железа (и таким образом перешёл в разряд высоконагруженных); возможно, это уже не первое масштабирование — не важно. Какие же проблемы могут возникнуть?

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

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

Published in: Internet
  • Be the first to comment

"Кластеры баз данных: делаем сложные вещи просто" Андрей Тихонов (Avito)

  1. 1. Кластеры баз данных: делаем сложные вещи просто Андрей Тихонов atikhonov@avito.ru Avito.ru DevOps
  2. 2. Содержание ● Как начинается Highload? ● Балансируем нагрузку на Backend ● Методы масштабирования БД ● Создаём кластер Redis/Memcached/Tarantool ● Создаём кластер PostgreSQL 2/47
  3. 3. Немножко статистики Avito ● 1M+ запросов в минуту к Backend ● 1Gb/s+ исходящий трафик (не считая картинки) ● 100K+ запросов в секунду на nginx-балансеры ● Терабайты или миллиарды картинок 3/47
  4. 4. Как начинается Highload?
  5. 5. Web-server Backend Database 5/47
  6. 6. Web-server Backend Database Cache 6/47
  7. 7. Web-server Backend * Database Cache 7/47
  8. 8. Web-server Backend * Database CacheStorage Queue 8/47
  9. 9. Web-server * Backend * Database * Cache *Storage * Queue * 9/47
  10. 10. Как работает Avito: 10/47
  11. 11. Балансируем нагрузку на Backend
  12. 12. 12/47 nginx.conf: ... location / { proxy_pass http://backend.local; } ...
  13. 13. 13/47 nginx.conf: ... upstream backend { server backend01.local:80; server backend02.local:80; server backend03.local:80; } ... location / { proxy_pass http://backend; } ...
  14. 14. Методы масштабирования БД
  15. 15. 15/47 Backend Database Read Write
  16. 16. 16/47 Backend Read Write MasterSlave Read Replication *репликация Master-Master здесь не рассматривается Репликация Master-Slave
  17. 17. 17/47 Backend Read Write Shard02Shard01 Read Write Шардирование
  18. 18. Создаём кластер Redis/Memcached/Tarantool
  19. 19. Проблемы 19/47 ● Установление подключения – долгая операция ● Малый срок жизни подключения ● Больше подключений – больше накладных расходов на сервере
  20. 20. Решаем проблемы с помощью Twemproxy* 20/47 ● Прозрачно проксирует на уровне протокола Memcached/Redis/Tarantool** ● Держит постоянное подключение к серверу ● Устанавливает мало подключений к серверу * см. также mcrouter, redis-proxy, redis-resharding-proxy, etc ** нужен патч
  21. 21. 21/47 twemproxy-redis-single.yml: alpha: listen: 127.0.0.1:22121 redis: true servers: - 127.0.0.1:6379:1
  22. 22. Шардируем с помощью Twemproxy 22/47 ● Автоматическое шардирование ● Поддерживает стойкое хэширование ● Автоматически группирует и конвейеризует запросы и ответы
  23. 23. 23/47 twemproxy-redis-shard.yml: beta: listen: 127.0.0.1:22122 redis: true distribution: ketama hash: murmur servers: - 127.0.0.1:6381:1 server1 - 127.0.0.1:6382:1 server2
  24. 24. Добавляем отказоустойчивость Redis-кластера 24/47 ● Master-Slave Replication средствами Redis
  25. 25. Master-Slave Replication средствами Redis 25/47 redis.conf (slave side): slaveof 192.168.10.1
  26. 26. Добавляем отказоустойчивость Redis-кластера 26/47 ● Master-Slave Replication средствами Redis
  27. 27. Добавляем отказоустойчивость Redis-кластера 27/47 ● Master-Slave Replication средствами Redis ● Автоматическое переключение в случае отказа мастера с помощью Redis Sentinel
  28. 28. Redis Sentinel 28/47 ● Мониторит состояние всех нод кластера ● Уведомляет об ошибках ● Автоматически промотирует slave до master в случае падения master ● Выступает в качестве провайдера конфигурации
  29. 29. Redis Sentinel 29/47 redis-sentinel.conf: sentinel monitor cluster01 192.168.10.1 6379 2 sentinel down-after-milliseconds cluster01 60000 sentinel failover-timeout cluster01 180000 sentinel parallel-syncs cluster01 1
  30. 30. Добавляем отказоустойчивость Redis-кластера 30/47 ● Master-Slave Replication средствами Redis ● Автоматическое переключение в случае отказа мастера с помощью Redis Sentinel
  31. 31. Добавляем отказоустойчивость Redis-кластера 31/47 ● Master-Slave Replication средствами Redis ● Автоматическое переключение в случае отказа мастера с помощью Redis Sentinel ● Прозрачное для клиента переключение с помощью HAProxy
  32. 32. HAProxy 32/47 ● TCP-прокси ● Балансирует нагрузку разными алгоритмами – Round-robin, least connections, first available, param* hash ● Primary/backup группы backend-серверов ● Различные способы проверки доступности серверов – TCP connect, protocol* check, TCP send-expect
  33. 33. HAProxy 33/47 haproxy-redis.conf: listen redis-cluster bind *:16379 option tcp-check balance roundrobin tcp-check send PINGrn tcp-check expect string +PONG tcp-check send info replicationrn tcp-check expect string role:master tcp-check send QUITrn tcp-check expect string +OK server redis01 192.168.10.1:6379 check port 6379 check inter 2s server redis02 192.168.10.2:6379 check port 6379 check inter 2s
  34. 34. Добавляем отказоустойчивость Redis-кластера 34/47 ● Master-Slave Replication средствами Redis ● Автоматическое переключение в случае отказа мастера с помощью Redis Sentinel ● Прозрачное для клиента переключение с помощью HAProxy
  35. 35. 35/47
  36. 36. Создаём кластер PostgreSQL
  37. 37. Проблемы 37/47 ● Одно подключение – один процесс, создание процесса – дорогостоящая операция ● План запросов и т. п. кэшируется внутри процесса, новое подключение – пустой кэш ● Малый срок жизни подключения ● Больше подключений – больше накладных расходов на сервере
  38. 38. Решаем проблемы с помощью PgBouncer* 38/47 ● Прозрачно проксирует на уровне протокола PgSQL ● Держит постоянное подключение к серверу ● Выполняет запросы до и после подключения ● Мультиплексирует клиентские подключения в трёх режимах: session, transaction, statement pooling * см. также PgPool
  39. 39. Решаем проблемы с помощью PgBouncer 39/47 pgbouncer.ini: [databases] main = host=db-main pool_size=5 connect_query= 'select prepare_statements_and_stuff()' [pgbouncer] pool_mode = transaction max_client_conn = 1024
  40. 40. Синхронная и асинхронная репликация 40/47 Синхронная: ● Надёжная ● Медленная Асинхронная: ● Быстрая ● Теряет ACID, так как слейвы отстают
  41. 41. Физическая и логическая репликация 41/47 Физическая: ● Полная копия всех данных ● Загружает I/O Логическая: ● Можно выбирать, какие данные копировать ● Загружает CPU
  42. 42. Создаём MSR-кластер 42/47 1 master, 1 slave: ● Распределяем нагрузку на чтение ● Нет отказоустойчивости 1 master, 2+ slave: ● Можем выдержать падение мастера
  43. 43. Создаём отдельную реплику для индексации 43/47 ● Логическая репликация: – Не вымывается кеш на мастере – Копируются только нужные данные ● Данные умещаются в RAM – нет медленного I/O
  44. 44. 44/47
  45. 45. Шардируем с помощью PL/Proxy* 45/47 ● Языковое расширение PostgreSQL ● Устанавливается на одной прокси-ноде ● Вся логика шардирования описывается в хранимых процедурах PostgreSQL ● Можно реализовать поддержку шард с MSR * см. также Citus
  46. 46. 46/47
  47. 47. Подведём итоги 47/47 ● Много кратковременных подключений к серверу – плохо, используем прокси ● Нужна отказоустойчивость – используем Master-Slave Replication, делаем несколько слейвов ● Слейвы должны быть не слабее мастера ● Данные не умещаются на одном сервере – шардируем на несколько серверов ● Все эти подходы можно комбинировать

×