Этот момент мы не очень хорошо умеем масштабировать. Для раздачи контента с высоким РПС / трафиком из одного файла лучше использовать CDN над S3.
основное что мы тут можем сдеалть - закэшировать файл (ну, точнее, включить настройку кэширования на бакете). Из-за особенностей реализации нашего кэширования это тоже не бесконечно масштабируемый вариант, но позволит повысить пропускную способность, так как защитит от высокой нагрузки диски с данными и шард базки.
Но вообще в общем случае S3 не создан для высокого рпс в 1 файл, тут лучше CDN либо какой-то еще аналог кэширующего сервиса над S3
Допустим размер шарда 1 Тб. Если занятое место достигает 90% (900 Гб), то мы говорим что шард перегружен по месту.
Допустим шард имеет 16 ядер процессора CPU. Если в среднем загружены более 14 ядер, то есть остается очень маленький запас и периодически мы упираемся в полку лимита - 16 ядер - то мы говорим что шард перегружен по CPU
То что записали в mds - станет ссылкой внутри строки pg. PG обеспечивает атомарность транзакций. С этой строкой всегда будет ассоциирована только эта ссылка на данные.
Добавили файл - он сначала записался в mds, потом строчка со ссылкой на данные записалась в PG.
Удалили файл - строчка попала в очередь на удаление, атомарно пропала из листинга пользователя.
Через какое-то время фоновый процесс cleanup приходит разгребать эту очередь, берет эту строчку и удаляет данные из mds.
Сплит ханков происходит по отдельному индексу (по хешу). Все что на этом этапе требуется - посчитать счетчики для нового ханка, то есть пересчитать объекты с хэшом в нужном диапазоне. Да, перебираем, но не 100к ключей, а сразу около половины - 50к ключей.
Листинг происходит не так как вы говорите. Листингу не нужно заходить в каждый ханк. Индекс по ключу все еще есть. Внутри шарда листинг отбирает нужное количество ключей (не больше 1000), идя последовательно по именам ключей. На шарде могут быть миллиарды объектов, но под условие запроса подходит не больше 1000 и именно их запрос листинга вытягивает с шарда. Другими словами, запрос листинга не знает о существовании ханков.
Да, интересная статья про лимиты! Получается в архитектуре Амазона есть ограничения на префикс, которые физически лежат на одном "шарде"?
В нашей схеме именно такого ограничения нет, мы можем разделить пространство ключей (или хешей) на достаточно маленькие кусочки и разнести их по разным шардам. Но каждый отдельный шард, конечно, имеет свои ограничения.
Насколько я понимаю, аналогия Event Notifications в Яндекс Облаке - Audit Trails.
Та сложность, о которой вы говорите, вероятно связана с необходимостью формировать событие очереди notifications в той же транзакции, что и само действие (например, object created)?
Очень рад такому контакту с зарубежным коллегой :)
Кеш метаданных над postgres есть, но он неконсистентный. Включаем его для клиентов по согласованию, это не является общим механизмом на всех. Он помогает разгружать базу для чтения.
Над сервисом-оракулом думали, но пока не выявили явной необходимости в нем.
Конкретные цифры лимитов RPS на шард не могу озвучить. Зависит от окружения, железа и вида нагрузки. Когда мы видим что нагрузка на шарды начинает превышать условные пороги - это знак к тому что пора расширять инсталяцию и докидывать новых шардов.
Глобально при помощи two-phase-commit (2PC) мы гарантируем что мы точно не оставили дубликата чанка на старом шарде, а также что мы не удалили чанк на старом шарде не создав его на новом (т.е. не потеряли метаданные).
Если на одном из шардов, участвующих в 2PC что-то пошло не так, то отдельный фоновый процесс потом ищет все висящие 2PC на всех шардах и понимает, в какую сторону нужно разрешить ситуацию. Либо откатывает PREPARED TRANSACTION, либо наоборот коммитит. Так обеспечивается согласованность метаданных объектов на разных шардах.
Если объект сохранился в MDS, а в базу нет, то в MDS останется мусор навсегда, а пользователь получит 500. Но это все-таки достаточно редкий тип фейлов, когда приложение падает именно в тот самый короткий момент пока мы не успели добавить запись в базу (а запрос в базу достаточно быстрый).
Про очередь счетчиков вы правы. Она тут фигурирует. И да, в той же транзакции, в которой мы добавляем запись о новом объекте в базу.
Если пользователь удалил объект по ключу и сразу же создал новый объект по такому же ключу, то никакой проблемы нет. В базе данных это будет новая строчка со своей ссылкой на данные в MDS.
Ситуация, когда пользователь удалил объект, но он еще показывается в листинге возможна, если не включен режим консистентности и листинг будет забираться с реплики. В Яндекс Облаке мы используем режим консистентности по умолчанию для всех пользователей. Во внутренней инсталяции Яндекса по умолчанию не используется режим консистентности, там такая ситуация возможна.
При удалении объекта из s3db в базе данных он удаляется не сразу, а перекладывается в отдельную очередь. Потом отдельный фоновый процесс cleanup разбирает очередь удалений и удаляет данные из MDS.
Нет, заранее ханки не создаются. Они создаются при сплите - когда живые ханки растут и в них становится больше 100к ключей. При превышении порога приходит сплиттер и делит ханк на 2 ханка по 50к.
Равномерность достигается за счет мувера. Мувер смотрит на каких шардах присутствует бакет, и выравнивает число ханков на каждом шарде присутствия, перенося ханки с более заполненных шардов на менее заполненные.
Здравствуйте, прошу прощения что не увидел ваш вопрос
Для очередей используем саму PG. Используем поле process_after для отодвигания взятых в работу строчек. В случае выполнения задачи строчка удаляется.
Этот момент мы не очень хорошо умеем масштабировать. Для раздачи контента с высоким РПС / трафиком из одного файла лучше использовать CDN над S3.
основное что мы тут можем сдеалть - закэшировать файл (ну, точнее, включить настройку кэширования на бакете). Из-за особенностей реализации нашего кэширования это тоже не бесконечно масштабируемый вариант, но позволит повысить пропускную способность, так как защитит от высокой нагрузки диски с данными и шард базки.
Но вообще в общем случае S3 не создан для высокого рпс в 1 файл, тут лучше CDN либо какой-то еще аналог кэширующего сервиса над S3
Подходит.
Исторически сложилось, что мы сделали шарды на PostgreSQL
А в некоторых новых регионах гусь использует YDB
Допустим размер шарда 1 Тб. Если занятое место достигает 90% (900 Гб), то мы говорим что шард перегружен по месту.
Допустим шард имеет 16 ядер процессора CPU. Если в среднем загружены более 14 ядер, то есть остается очень маленький запас и периодически мы упираемся в полку лимита - 16 ядер - то мы говорим что шард перегружен по CPU
Такое может быть, тогда в mds останется мусор, а в пользователю вернется 500-ка
Не нужно поддерживать атомарность между pg и mds
То что записали в mds - станет ссылкой внутри строки pg. PG обеспечивает атомарность транзакций. С этой строкой всегда будет ассоциирована только эта ссылка на данные.
Добавили файл - он сначала записался в mds, потом строчка со ссылкой на данные записалась в PG.
Удалили файл - строчка попала в очередь на удаление, атомарно пропала из листинга пользователя.
Через какое-то время фоновый процесс cleanup приходит разгребать эту очередь, берет эту строчку и удаляет данные из mds.
Верно. И это происходит из коробки средствами postgres, муверу совсем не требуется совершать для этого отдельных действий.
Ну и индекс по хешу - не в пределах ханка, а в пределах всего шарда, это обычный индекс внутри базы данных
Сплит ханков происходит по отдельному индексу (по хешу). Все что на этом этапе требуется - посчитать счетчики для нового ханка, то есть пересчитать объекты с хэшом в нужном диапазоне. Да, перебираем, но не 100к ключей, а сразу около половины - 50к ключей.
Листинг происходит не так как вы говорите. Листингу не нужно заходить в каждый ханк. Индекс по ключу все еще есть. Внутри шарда листинг отбирает нужное количество ключей (не больше 1000), идя последовательно по именам ключей. На шарде могут быть миллиарды объектов, но под условие запроса подходит не больше 1000 и именно их запрос листинга вытягивает с шарда. Другими словами, запрос листинга не знает о существовании ханков.
?
Да, интересная статья про лимиты! Получается в архитектуре Амазона есть ограничения на префикс, которые физически лежат на одном "шарде"?
В нашей схеме именно такого ограничения нет, мы можем разделить пространство ключей (или хешей) на достаточно маленькие кусочки и разнести их по разным шардам. Но каждый отдельный шард, конечно, имеет свои ограничения.
Насколько я понимаю, аналогия Event Notifications в Яндекс Облаке - Audit Trails.
Та сложность, о которой вы говорите, вероятно связана с необходимостью формировать событие очереди notifications в той же транзакции, что и само действие (например, object created)?
Очень рад такому контакту с зарубежным коллегой :)
Кеш метаданных над postgres есть, но он неконсистентный. Включаем его для клиентов по согласованию, это не является общим механизмом на всех. Он помогает разгружать базу для чтения.
Над сервисом-оракулом думали, но пока не выявили явной необходимости в нем.
Конкретные цифры лимитов RPS на шард не могу озвучить. Зависит от окружения, железа и вида нагрузки. Когда мы видим что нагрузка на шарды начинает превышать условные пороги - это знак к тому что пора расширять инсталяцию и докидывать новых шардов.
Когда режим консистентности включен - он обеспечивается просто за счет хождения в мастер. Сервиса-оракула нет (к слову, у AWS кажется такой есть).
Наверное можно и так сказать
Глобально при помощи two-phase-commit (2PC) мы гарантируем что мы точно не оставили дубликата чанка на старом шарде, а также что мы не удалили чанк на старом шарде не создав его на новом (т.е. не потеряли метаданные).
https://www.postgresql.org/docs/current/two-phase.html
Если на одном из шардов, участвующих в 2PC что-то пошло не так, то отдельный фоновый процесс потом ищет все висящие 2PC на всех шардах и понимает, в какую сторону нужно разрешить ситуацию. Либо откатывает PREPARED TRANSACTION, либо наоборот коммитит. Так обеспечивается согласованность метаданных объектов на разных шардах.
Если объект сохранился в MDS, а в базу нет, то в MDS останется мусор навсегда, а пользователь получит 500. Но это все-таки достаточно редкий тип фейлов, когда приложение падает именно в тот самый короткий момент пока мы не успели добавить запись в базу (а запрос в базу достаточно быстрый).
Про очередь счетчиков вы правы. Она тут фигурирует. И да, в той же транзакции, в которой мы добавляем запись о новом объекте в базу.
Сохранить в MDS и потом положить запись со ссылкой на данные в MDS в базу. В этом процессе очередь не фигурирует
сразу отправляется 200 OK
Если пользователь удалил объект по ключу и сразу же создал новый объект по такому же ключу, то никакой проблемы нет. В базе данных это будет новая строчка со своей ссылкой на данные в MDS.
Ситуация, когда пользователь удалил объект, но он еще показывается в листинге возможна, если не включен режим консистентности и листинг будет забираться с реплики. В Яндекс Облаке мы используем режим консистентности по умолчанию для всех пользователей. Во внутренней инсталяции Яндекса по умолчанию не используется режим консистентности, там такая ситуация возможна.
При удалении объекта из s3db в базе данных он удаляется не сразу, а перекладывается в отдельную очередь. Потом отдельный фоновый процесс cleanup разбирает очередь удалений и удаляет данные из MDS.
Нет, общего перехода на YDB нет, выбираем технологии под задачи.
К слову, в некоторых новых регионах гусь использует YDB, так что в зависимости от условий мы можем выбирать разные технологии.
Нет, заранее ханки не создаются. Они создаются при сплите - когда живые ханки растут и в них становится больше 100к ключей. При превышении порога приходит сплиттер и делит ханк на 2 ханка по 50к.
Равномерность достигается за счет мувера. Мувер смотрит на каких шардах присутствует бакет, и выравнивает число ханков на каждом шарде присутствия, перенося ханки с более заполненных шардов на менее заполненные.