Этот репозиторий создается в рамках курса по System design.
Описание функциональности, предоставленное бизнесом:
- публикация постов из путешествий с фотографиями, небольшим описанием и привязкой к конкретному месту путешествия;
- оценка и комментарии постов других путешественников;
- подписка на других путешественников, чтобы следить за их активностью;
- поиск популярных мест для путешествий и просмотр постов с этих мест в виде ТОПа мест по странам и городам;
- общение с другими путешественниками в личных сообщениях;
- просмотр ленты других путешественников
К функциональным требованиям добавим:
- существует общая лента постов путешественников, на которых он подписан
- можно посмотреть историю своих лайков
- в сообщениях можно обмениваться только текстом и изображениями
- в ленте показывается 20 постов, потом она догружается
Нефункциональные требования:
- Аудитория:
- пользователи по всему миру
- DAO около 1_000_000
- пользователи будут делать посты в путешествиях, то есть пачками, 4 поста в день во время путешествия. В остальное время в среднем будут открывать ленту раз в день и ставить около 15 лайков и 5 комментариев. Вести переписку в среднем час в день по сообщению в минуту c 5ю собеседниками
- Сезонность: в основном отпуска приходятся на май-сентябрь. Вне сезона каждые выходные (6 дней в месяц) в отпуск уходит 10% пользователей, в сезон каждый пользователь уйдет на неделю, то есть нарузка повысится в 3,8 раза.
- Хранить данные нужно всегда, потеря их критична
- Лимиты и ограничения:
- у пользователя будет не больше 1000 подписок
- для пользователя возможна публикация не более 100 постов в день
- Временные ограничения:
- пост должен публиковаться за 1 секунд
- сообщения должны доходить за 0.5 секунды
- лента должна загружаться не дольше 5 секунд
- Доступность приложения: приложение может быть недоступно не более суток в год, то есть 99.5%
RPS_read_lenta = 1_000_000 * 3 (сколько загрузок ленты) / 86400 = 35
RPS_read_messages = 1_000_000 * 5 (сколько открывалось диалогов) * 50 (сообщений в них) / 86400 = 2900
RPS_read_comments = 35 (rps ленты) * 20 (столько постов в ленте) = 700
RPS_write_post = 1_000_000 * 0.1 * 4 * (6/30.5) / 86400 = 1 - вне сезона, 4 в сезон
RPS_write_messages = 1_000_000 * 60 (сообщений в день) / 86400 = 695
RPS_write_like = 1_000_000 * 15 / 86400 = 174
RPS_write_comments = 1_000_000 * 5 / 86400 = 58
T_read_lenta = 35 * 20 постов в ленте * (500 kB картинка + (500B текст + 8B геолокация + идентификатор пользователя 8B + 4B лайки + 10 * 100B комментарии)) = 350mB картинок + 1mB
T_read_messages = 2900 * 100B = 290kB
T_read_comments = 700 * 10 комментариев к каждому посту * (100B текст + 4B идентификатор пользователя) = 728 kB
T_write_post = 1 * (500 kB картинка + (500B текст + 8B геолокация + идентификатор пользователя 8B)) = 0,5 mB картинок + 0,5 kB (вне сезона), в 4 раза больше в сезон
T_write_messages = 695 * 100B = 70kB
T_write_like = 174 * 4B идентификатор пользователя = 700B
T_write_comments = 58 * (100B текст + 4B идентификатор пользователя) = 6 kB
Data_per_year = 86400 * 365 * ((5/12 (сезон)*8 kB + 7/12*6.5 kB) + 728kB)= 23 TB
Traffic_per_second = 1mB + 728 kB + 2Kb + 6 kB ~ 2 mB
IOPS ~ read(35 * 20 + 7000 ) + write(1 + 174 + 58) = 7933 (в сезон увеличивается объем данных из-за большого количества картинок в постах, частота запросов увеличивается незначительно)
Тип | Объем | IOPS | Пропускная способность |
---|---|---|---|
HDD | до 32ТБ | 100 | 100 МБ/с |
iops слишком мал
Тип | Объем | IOPS | Пропускная способность |
---|---|---|---|
SSD (SATA) | до 100ТБ | 1 000 | 500 МБ/с |
Получается 8 SSD(SATA) диск на 4 TB
Допустим в системе регистрируется 1 тыс пользователей каждый день или 0.1 в секунду
Data_per_year = 86400 * 365 * (0.1 * (2b (один символ) *(256(email)+100(username)+100(avatar_url)) = 300 mB
IOPS ~ 35 + 0.1 + 700 = 736 (информация о пользователе будет запрашиваться при чтении каждого поста и коммента)
Можно выделить 1 GB в другом SATA диске
Data_per_year = 86400 * 365 * 70kB = 2,5 TB
IOPS ~ 2900 + 695 = 3595
Тип | Объем | IOPS | Пропускная способность |
---|---|---|---|
SSD (SATA) | до 100ТБ | 1 000 | 500 МБ/с |
Получается 2 SSD(SATA) диска на 1 TB и 2 на 512 GB
Тип | Объем | IOPS | Пропускная способность |
---|---|---|---|
SSD (nVME) | до 30ТБ | 10 000 | 3 ГБ/с |
Получается 1 SSD(nVME) диска на 4 TB
Дешевле взять 4 sata диска
Data_per_year = 86400 * 365 * 500kb * ((5/12 (сезон)*4 + 7/12*1) + 695 (сообщений) * 0.1 + 0.1 (аватарки)) = 1123 TB
IOPS ~ (35*20 (посты) + 0.1 * 695 (сообщения)) * 2 (за аватарки) = 1539
Тип | Объем | IOPS | Пропускная способность |
---|---|---|---|
SSD (SATA) | до 100ТБ | 1 000 | 500 МБ/с |
Нужно 12 таких дисков
Для ленты применим репликацию master-slave, чтобы обеспечить большую отказоустойчивость, а также так как нагрузка на чтение (7700 rps к диску) превышает нагрузку на запись (233 rpc к диску). Потеря данных не так критична, поэтому репликация будет ассинхронная. Replication factor = 2, тогда надо 4 диска по 6 TB в каждой реплике.
Для сообщений репликация будет использована для повышения отказоустойчивости, тип master-slave, синхронная, так как потеря данных здесь кртична. Replication factor = 2. Также будет использоваться шардирование по chat_id (key based) для распределения нагрузки. 2 диска на 1.5 TB на каждый шард (один основной, другой реплика), то есть суммарно 4 диска на систему
Для хранения информации о пользователях будет реализована синхронная master-slave репликация, в случае падения будет обеспечена быстрое восстановление работы, так что нагрузка будет только на master, slave запасная. Replication factor = 2, по 1 GB SATA диска.
Для медиа будет использоваться master-master репликация, два мастера будут находится в разных датацентрах, распределенных по географическому признаку, чтобы уменьшить время задержки сети
Для ленты 4 хоста = 8 с репликацией
Для сообщений 2 хоста = 4 с репликацией
Для информации о пользователях 1 хост = 2 с репликацией
Для медиа будет 1 хост = 2 с репликацией