Pull to refresh
15
0
Владимир Бородин @dev1ant

Пользователь

Send message
Изначально ClickHouse был NoSQL-СУБД...

Это неправда. ClickHouse с самого появления умел SQL.

А как вы подключаетесь к базам без публичного адреса из on prem? VPN, Direct connect? Кажется, что пока единственным работающим решением будет на DNS-серверах в on prem (они же есть?) сделать форвардинг зоны mdb.yandexcloud.net в DNS-сервер Облака для вашей сети. Но это вряд ли можно назвать правильным решением.


В планах сейчас такого нет, потому что вы первый, кто спрашивает. Рекомендую это добавить в https://cloud.yandex.ru/community, чтобы другие люди эту идею лайкали и мы понимали приоритет этой задачи.

Возможно я плохо выразился. Я не хотел делать наброс или еще что.

Просто Вы из довольно частного случая сделали довольно общий вывод.


Вы что-то сделали кроме рекомендации в личку "увеличьте диски, меньше пишите в базу"?

Да, у нас теперь значения параметров min_wal_size и max_wal_size выставляются в зависимости от размера диска. Ещё подкрутили параметры архивации WAL, чтобы в таких ситуациях база писала медленнее, а архивация работала быстрее. Ну и запланировали сделать auto resize диска, про это пишу уже не первый раз.

Яндекс.Диск:
image


Облако:
image


А вообще ваш комментарий не имеет никакого отношения к посту.

Но я точно уверен, что с тех пор код не менялся, а база живет на похожей self hosted конфигурации без сбоев.

"У меня такая же нога и не болит" © Очевидно, что есть отличия в конфигурации. Например, вы с self-hosted базы архивируете WAL? Если нет, то вероятность закончиться месту под WAL'ом при активной записи, конечно же, сильно ниже, но тогда вы теряете возможность восстановиться из бэкапа на произвольный момент времени (а не только то время, когда был сделан бэкап).


BTW, указанный вами запрос некорректный. Функция pg_relation_size не покажет вам размеры индексов, правильнее использовать pg_total_relation_size.

Посмотрел ещё раз в это обращение. Возможно, база и росла со скоростью 1 МБ в день, но тогда вы её агрессивно перезаписывали, потому что в логах было такое:


[ 2019-07-02 18:45:49.881 MSK ,,,173628,00000 ]:LOG: checkpoints are occurring too frequently (49 seconds apart) [ 2019-07-02 18:45:49.881 MSK ,,,173628,00000 ]:HINT: Consider increasing the configuration parameter "max_wal_size".


Т.е. писали вы явно много. Про это вам support отвечал.


Ну и после того, как вы удалили кластер, к вам приходил менеджер, расспрашивал о произошедшем и рассказывал, почему и как такое произошло. А потому извините, но я буду считать ваш комментарий к статье набросом, а не конструктивным feedback'ом.

Cron этот существует с незапамятных времён. Потому что всё описанное в статье работает внутри компании (для разработчиков Яндекса) с 2016 года.

Дай, пожалуйста, номер обращения в support. И ещё вопрос, кластер состоял из одного хоста?
На хостах есть cron, который раз в минуту проверяет оставшееся место и если осталось меньше 3%, уводит базу в read-only, чтобы остаться доступным хотя бы на чтение. Ну и в обратную сторону, соответственно, если место освободилось. Проблема в том, что на диске самого маленького объёма (10 ГБ) эти 3% места могут закончиться сильно быстрее, чем за минуту. Тут поведение у нас ничем не отличается от поведения конкурентов или ситуации, которая была бы у вас в случае базы в вашей собственной виртуалке/на железе.

Системным же решением нам видится автоматический resize диска при заканчивающемся месте (с возможностью это выключить пользователем, конечно). Про это написано в планах на будущее.
– Кроме Amazon RDS есть и другие облачные managed postgres. Сталкивались ли вы, например, с сервисом Яндекса?

Андрей: Я сталкивался с их виртуалками и они мне не очень понравились — там NVMe у дисков не очень честный. По сути там диски, подключенные по сети.

Если говорить про обычные виртуалки в Яндекс.Облаке, то диски только сетевые, да, чтобы была избыточность и можно было мигрировать виртуалку в случае смерти гипервизора. У всех конкурентов в managed-сервисах (Amazon RDS, Google Cloud SQL и т.п.), кстати, только такие и есть.

Андрей: В Яндекс Облако мне прокомментировали, что в DB as service у них честный NVMe, но я с этим сервисом пока не сталкивался. Видимо, там немного другая архитектура на уровне предоставления ресурсов.

Если говорить про Yandex Managed Service for PostgreSQL, то пользователю доступен выбор – сетевые или локальные. Последние сильно быстрее, но в таком случае меньше трёх нод запустить нельзя, потому что локальные диски сами по себе избыточность не обеспечивают и сохранность данных обеспечивается средствами СУБД.
Я правильно понял, что получилось 1309 TPS на виртуалке с network-nvme и 1226 TPS в managed postgresql с local-nvme?
pgbench -i -s 100

Это ведь ~ 1,5 ГБ данных. При 32 ГБ памяти все данные влезут в кэш.

pgbench -c 10 -T 60

10 соединений для данных ресурсов (8 ядер) явно маловато. По сути получился тест, который гарантированно упрётся в I/O на запись. В таком случае имеет смысл попробовать в Yandex Managed PostgreSQL при создании выбрать local-nvme, они быстрее.

Я бы для данных ресурсов инициализировал со scaling factor 1000. И ещё интересно было бы посмотреть стрельбу, которая в процессор упрётся, вроде такой:
pgbench -j 4 -c 32 -T 60 --select-only
Суть конфликта в том, что в результате наката statement'ов этих транзакций, упорядоченных по времени коммита, на реплике получится другой результат.

Например, в транзакции B в табличке foo заменили какое-то поле с 1 на 2 во всех строчках. Транзакция C читает чиселку из foo и получает 1, потому что B ещё не закоммитилась. Транзакция C записывает вычитанную чиселку в табличку bar и делает что-то ещё, повисая на блокировке. Транзакция B коммитится, транзакция А читает чиселку из foo (получает уже 2), пишет её в табличку baz и коммитится. Транзакция C успешно коммитится. Итого на мастере получается следующая картина маслом:
foo: 2,
bar: 1,
baz: 2.

Если же теперь повторить транзакции на реплике по времени коммита, то получится вот так:
foo: 2,
bar: 2,
baz: 2.

Отсюда вывод, что применять такой лог запросов по timestamp'у коммита нельзя, а другого timestamp'а у вас как бы и нет. Можно было бы писать timestamp каждого statement'а (вернее, когда БД вернула ответ на него), но во-первых, это уже включает в себя передачу по сети, которая может вносить произвольный лаг, а во-вторых, это не покрывает работы триггеров или хранимую логику.

Короче, реализовать свою логическую репликацию сильно сложнее, чем кажется. Не стоит так делать.
Обо всём этом я рассказывал тут — https://events.yandex.ru/lib/talks/3202/

И снова я вам порекомендую внимательно почитать, в этот раз комментарий от Botkin. В нём есть ссылка, по которой можно увидеть, что нахваливаемый вами dm-cache не является решением для automated tiering.


Ещё раз повторю, что 10 человеко-лет мы потратили совсем не на "скрипты". И фраз "всё учли" я что-то тоже не припоминаю.

Скажем так, в Яндекс.Диске самая большая инсталляция MongoDB в мире. Да, версия 3.0 была большим шагом вперёд, но наш опыт (а не пустое мнение, как вы пишите) говорят о слабой применимости монги для задачи Яндекс.Почты. Да и сейчас ребята из 10gen ещё детские болячки долечивают — https://jepsen.io/analyses/mongodb-3-4-0-rc3.


Разделение данных на горячие/холодные внутри шарда мы только хотим сделать, а не сделали. И кучу времени мы потратили совсем не на это. Рекомендую вам сначала почитать статью/посмотреть презентацию или видео, прежде чем писать комментарии про синюю изоленту у нас.

На самом деле всё не так просто, как вы пишите.

1. Бэкендов, которые что-то модифицируют в базе, много. Время на них, конечно, синхронизируется, но NTP не даёт нужной точности.

2. Даже если предположить, что время идеально синхронизировано, в READ COMMITTED (уровень изоляции по-умолчанию и мы используем его) видны изменения уже закомиченных конкурентных транзакций. Транзакция А могла прочитать что-то, что было закомичено в транзакции B, но завершиться после транзакции C, которая изменений в B не видела в момент чтения. Потому 100% консистентности достичь будет сложно.

3. Накатывать такой логический лог запросов с параллелизмом сложно, а в один поток оно упрётся в одно ядро при хоть какой-то нагрузке. Именно потому в postgres'е WAL бинарный и накат на репликах легко справляется одним ядром, не отставая, упираясь в ядро.
Выше речь идёт про перенос между физическими шардами, никаких NAS/SAN там и близко нет из соображений производительности.

Что касается разделения данных на горячие и холодные внутри шарда, то стоит об этом подумать, хотя я бы предпочёл, чтобы база про это знала при планировании запросов. А подскажите какое-нибудь программное решение для linux'а?
Задан жёстко. Логика переноса лежит в том же репозитории, что и схема БД с кодом и тестами. На каждое изменение гоняются покоммитные тесты, проверяющие в т.ч. и работу трансфера.

Шарпей — это наш сервис шардирования, который хранит соответствие пользователя и шарда. И в нём, конечно, при переезде происходит обновление данных. Про это есть в презентации.

Перенос можно запустить либо руками (скрипт/jenkins job), либо это делает автоматика по весьма тупым критериям (не шевелился никак кроме покладки полгода — в sata и т.п.). Сейчас думаем в это место вкрячить ML, чтобы критерии самим не прописывать.


FK, конечно же есть, многие из них deferrable. Потому данные переносятся потаблично в правильном порядке. Параллелизма для пользователя нет (один пользователь — один поток). Потребление памяти константное, потому что копирование делается поточно с помощью COPY пачками фиксированного размера.


Глобально же перенос выглядит так. Открываются транзакции в шард-источник, где пользователь блокируется на запись, в шард приёмник и в шарпей. В случае успешного переноса всё коммитится с 2PC. В случае ошибок откатывается. Во время переноса ящик пользователя в read-only, но это в общем случае не проблема, потому что ящик на 10**5 писем переносится за единицы секунд.

Information

Rating
Does not participate
Works in
Registered
Activity