Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Олег Блохин "NALSD. Подход Google к проектированию распределённых приложений."

DotNetRu
August 08, 2019

Олег Блохин "NALSD. Подход Google к проектированию распределённых приложений."

Все мы участвуем в проектировании систем. Сознательно или нет. Иногда делая десятки UML диаграмм, а иногда на салфетке или просто в уме.

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

Гугл предлагает инженерный подход для решения вопроса: Non Abstract Large Scale System Design. Это набор инженерных практик при проектировании сервиса, которые позволяют меньше ошибаться. Я расскажу о том, как их применять.

DotNetRu

August 08, 2019
Tweet

More Decks by DotNetRu

Other Decks in Programming

Transcript

  1. Data Model: Promocodes: id promocode bonusActionId + isRemoved Interface: add

    promocode add multiple promocodes delete promocode
  2. 100 заказов/в минуту * 60 минут/час * 15 рабочих часов

    в день * 30 дней = 2700000 - заказов в месяц Data Model: Promocodes: id promocode bonusActionId + isRemoved Calculations: Interface: add promocode add multiple promocodes delete promocode
  3. 100 заказов/в минуту * 60 минут/час * 15 рабочих часов

    в день * 30 дней = 2700000 - заказов в месяц Пускай опаздывает каждый сотый заказ Data Model: Promocodes: id promocode bonusActionId + isRemoved Calculations: Interface: add promocode add multiple promocodes delete promocode
  4. 100 заказов/в минуту * 60 минут/час * 15 рабочих часов

    в день * 30 дней = 2700000 - заказов в месяц Пускай опаздывает каждый сотый заказ 27000 промокодов в месяц только на потерянных заказах Чтобы было проще считать возьмём за 30 000 360 000 промокодов в год 1 800 000 - пять лет Data Model: Promocodes: id promocode bonusActionId + isRemoved Calculations: Interface: add promocode add multiple promocodes delete promocode
  5. 1 800 000 промокодов Пусть управляющий пиццерией вставляет 100 промокодов

    разом Хотим удалить вставить новый без повторений Пусть у нас индекс на колонку promocode log2(1 800 000) ~= log2(1024 * 1024 * 2) ~= 21 21 чтение В худшем случае, таблицы в памяти нет, значит читаем с диска 21 * 60 = 1260 операций чтения В худшем случае (random access на HDD) при 100 iops, 12 секунд Но тк 1800000*30байт ~= 60 Мб никакого random access не будет, несколько iops и 150Mb/s с диска. Целиком засосёт в память меньше чем за секунду. Кроме того промокоды скорее всего горячие в памяти. Data Model: Promocodes: id promocode bonusActionId + isRemoved Calculations: Interface: add promocode add multiple promocodes delete promocode
  6. Data Model: Promocodes: id promocode bonusActionId + isRemoved Evaluation: Interface:

    add promocode add multiple promocodes delete promocode - Это возможно реализовать? Да - Можем лучше? Определённо да - Можно сделать джобу, которая перекладывает 
 не удалённые бонусные акции старше 1 месяца в архивную таблицу 
 и удаляет из оперативной - Если добавить индекс на isRemoved, 
 то сразу отсекаем неиспользуемые промокоды. - Data pipeline? - выглядит слишком сложно для такой задачи, 
 но может быть неплохой вариант, если это частый паттерн. - Это надёжно? Оригинальный механизм не защищает от ситуации, когда промокодов окажется больше, чем мы рассчитывали. Джона надёжнее и даёт пространство для манёвра.
  7. Yo! • Users: • 100 000 пользователей • 10 yo!

    в день равномерно • x10 непредсказуемые всплески • Requirements: • 99,9% от принятых запросов доставлены за 100ms • 99,9% запросов должны заканчиваться OK • 200 OK = гарантия доставки
  8. Yo! Доступное оборудование Common Server 2 CPU x 2,3 GHz

    4 Gb RAM 1Gbit net 1Tb SSD 
 SLA: 99,5% availability Гарантии независимые! Magic Load Balancer лоад балансер, который мы можем наделить любыми свойствами [в рамках разумного]
  9. Requirement: 99,9% от принятых запросов доставлены за 100ms Calculations Post:

    100 000 users x 10 req/day / 90 000 sec/day ~= 10 QPS x10 пик: 10QPS * 10 * 1KB = 100KBps 
 Get: 100 000 x (1req/100ms) = 1 000 000 QPS 1000 000QPS x 1KB = 1GB/sec = 8Gbit/sec 
 = 8 машин, чтобы держать трафик
  10. Requirement: 99,9% от принятых запросов доставлены за 100ms Calculations Post:

    100 000 users x 10 req/day / 90 000 sec/day ~= 10 QPS x10 пик: 10QPS * 10 * 1KB = 100KBps 
 Get: 16KB per connection 16Kb * 100 000 users = 1.6 GB RAM 
 100 000 sockets... OH SHI..! Одна машина держит ~65K сокетов, нам мало
  11. Requirement: 99,9% от принятых запросов доставлены за 100ms Calculations Post:

    100 000 users x 10 req/day / 90 000 sec/day ~= 10 QPS x10 пик: 10QPS * 10 * 1KB = 100KBps 
 Get: 16KB per connection 16Kb * 100 000 users / 2 server = 0.8 GB RAM = Post = 100 KBPs 
 100 000 / 2 server = 50k sockets 
 Total Traffic: 200KBps при 100QPs 20KBps при 10Qps
  12. Requirement: 99,9% от принятых запросов доставлены за 100ms Calculations Что

    будет в базе: 100Qps = 100 Inserts/sec x10: 100 select all 100 update by id 
 Если весь день не будет разгребаться очередь, то: 1 000 000 записей по 30 байт = 30Мбайт. 
 (30 * 10 * 2) = 600 Мбпс Терпимо
  13. Requirement: 99,9% от принятых запросов доставлены за 100ms Evaluation -

    Inconsistency: Если человек не подключен, мы физически не можем доставить за 100 мс. Объясняем бизнесу, договариваемся: что требование будет работать только если оба человека запустили приложение и находятся онлайн. - Is <design> possible? yes - Can we do better? - Если не можем обеспечить требование в 100ms. 
 Перекладываем сообщения в "медленную" очередь. Которую будем трогать раз в 30 секунд. - Может быть отказаться от HTTP в пользу чистого TCP, или от TCP в пользу WebSockets?
  14. Выводы Чтобы делать NALSD, необходимо: - Отлично знать свой стек

    и соседние технологии, чтобы свести к минимуму фантазии - Уметь количественно оценивать параметры системы