Замечания
В случаях, когда происходит обращение к случайным единичным строкам таблицы, фактический порядок данных в этой таблице не важен. Но если обращения к одним данным происходят чаще, чем к другим, и есть индекс, который собирает их вместе, применение команды может быть полезным. Например, когда из таблицы запрашивается диапазон индексированных значений, либо одно индексированное значение, которому соответствуют несколько строк, может помочь, так как страница таблицы, найденная по индексу для первой искомой строки, скорее всего, будет содержать и все остальные искомые строки. Таким образом, кластеризация помогает соптимизировать обращения к диску и ускорить запросы.
может переупорядочить таблицу, выполнив либо сканирование указанного индекса, либо (для индексов-B-деревьев) последовательное сканирование, а затем сортировку. Наилучший по скорости вариант будет выбран, исходя из имеющейся статистической информации и параметров планировщика.
Когда выбирается сканирование индекса, создаётся временная таблица, содержащая данные целевой таблицы по порядку индекса. Также создаются копии всех индексов таблицы. Таким образом, для этой операции требуется объём дискового пространства не меньше, чем размер таблицы и индексов в сумме.
В случае выбора последовательного сканирования и сортировки создаётся ещё и временный файл для сортировки, так что пиковым требованием будет удвоенный размер таблицы плюс размер индексов. Этот метод часто быстрее, чем сканирование по индексу, но если требование к дисковому пространству неприемлемо, можно отключить его выбор, временно установив в .
Перед кластеризацией рекомендуется установить в достаточно большое значение (но не больше, чем объём ОЗУ, который вы хотите выделить для операции ).
Так как планировщик записывает статистику, связанную с порядком таблиц, для вновь кластеризуемых таблиц рекомендуется запускать ANALYZE. В противном случае планировщик может ошибиться с выбором плана запроса.
Описание
Оператор указывает Postgres Pro кластеризовать таблицу, заданную параметром , согласно индексу, заданному параметром . Указанный индекс уже должен быть определён в таблице .
В результате кластеризации таблицы её содержимое физически переупорядочивается в зависимости от индекса. Кластеризация является одноразовой операцией: последующие изменения в таблице нарушают порядок кластеризации. Другими словами, система не пытается автоматически сохранять порядок новых или изменённых строк в соответствии с индексом. (Если такое желание возникает, можно периодически повторять кластеризацию, выполняя команду снова. Кроме того, если для заданной таблицы установить параметр меньше 100%, это может помочь сохранить порядок кластеризации при изменениях, так как изменяемые строки будут помещаться в ту же страницу, если в ней достаточно места.)
Когда таблица кластеризована, Postgres Pro запоминает, по какому именно индексу. Форма повторно кластеризует таблицу по тому же индексу. Для установки индекса, который будет использоваться для будущих операций кластеризации, или очистки предыдущего значения можно также применить команду или формы команды ALTER TABLE.
без параметров повторно кластеризует все ранее кластеризованные таблицы в текущей базе данных, принадлежащие пользователю, вызывающему команду, или все такие таблицы, если её вызывает суперпользователь. Эту форму нельзя выполнять внутри блока транзакции.
Сравнение методов интерполяции
Хотя только алгоритм Мультимасштабный (OPTICS) применяет для определения кластеров график достижимости, этот график может использоваться для иллюстрации отличий методов друг от друга. Для данной иллюстрации представленный далее график достижимости будет использован для объяснения различий трех методов. На графике отображены кластеры различной плотности и разных расстояний разделения. Мы с помощью этого изображения изучим результаты использования каждого из методов кластеризации.
Концептуальный график достижимости с кластерами точек разной плотности и с различными расстояниями между ними.
Для Заданного расстояния (DBSCAN) представьте себе линию, пересекающую график на указанном Расстоянии поиска. Области под Расстоянием поиска соответствуют кластерам, а пики над Расстоянием поиска – точкам шума. Алгоритм DBSCAN – самый быстрый из методов кластеризации,но применим только в случае, если четко ясно, какое Расстояние поиска использовать и это Расстояние поиска подходит для всех потенциальных кластеров. Это происходит в ситуации сходных плотностей всех важных кластеров.
изображение Расстояния поиска в алгоритме DBSCAN
Для Самонастраивающегося (HDBSCAN) алгоритма расстояния достижимости можно рассматривать как вложенные уровни кластеров. Каждый уровень кластеризации приведет к обнаружению разных наборы кластеров. Самонастраивающийся (HDBSCAN) алгоритм выбирает, на каком уровне кластеров в каждом наборе вложенных кластеров будут созданы наиболее стабильные кластеры, включающие максимально возможное количество объектов и не содержащие шумов. Подробнее об алгоритме см. в прекрасной документации от создателей HDBSCAN. Самонастраивающийся (HDBSCAN) является наиболее ориентированным на данные методом кластеризации, для него требуется минимум участия пользователя.
Изображение иерархических уровней, используемых алгоритмом HDBSCAN для поиска наилучших, максимально стабильных кластеров
В алгоритме Мультимасштабный (OPTICS) определение кластеров основывается не на конкретном расстоянии, а на пиках и впадинах графика. Предположим, что у пика есть уровни: малый, средний и большой.
Изображение интенсивности пиков на графике достижимости
Если выбрать очень высокую Чувствительность кластера, то, как правило, все пики – от малых и до больших – будут считаться разделяющими классы (что приводит к большому числу классов).
Изображение влияния высокой Чувствительности кластеров в алгоритме OPTICS и соответствующих кластеров
При выборе средней Чувствительности кластеров будут использоваться только Большие и Средние пики, а малые – нет.
Изображение влияния средней Чувствительности кластеров в алгоритме OPTICS и соответствующих кластеров
При выборе низкой Чувствительности кластеров будут использоваться только Большие пики, в результате чего будет обнаружено наименьшее число кластеров.
Изображение влияния низкой Чувствительности кластеров в алгоритме OPTICS и соответствующих кластеров
Консолидация и сборка решения
В примерах я буду говорить о том, как принципиально должно выглядеть решение, а в коде — как это вышло у меня. Для создания кластера вовсе не обязательно иметь Kubernetes (есть пример docker-compose) или Docker в принципе. Просто тогда, все описанное будет полезно, не как решение типа CPM (Copy-Paste-Modify), а как руководство по установке cо снипетами.
Primary и Standby вместо Master и Slave
Почему же коллеги из Postgresql отказались от терминов “Master” и “Slave”?.. хм, могу ошибаться, но ходил слух, что из-за не-полит-корректности, мол, что рабство это плохо. Ну и правильно.
Первое что нужно сделать — включить Primary сервер, за ним первый слой Standby, а за тем второй — все согласно поставленной задачи. Отсюда получаем простую процедуру по включению обычного Postgresql сервера в режиме Primary/Standby с конфигурацией для включения Streaming Replication
Как только мы получили первый сервер кластера, можем включать Stanby, который знает, где находится его Primary.
Моя задача здесь свелась к сборке универсального образа Docker Image, который включается в работу, в зависимости от режима, как то так:
-
Для Primary:
- Конфигурирует Repmgr (о нем немного позже)
- Создает базу и пользователя для приложения
- Создает базу и пользователя для мониторинга и поддержки репликации
- Обновляет конфиг() и открывает доступ пользователям извне()
- Запускает Postgresql сервис в фоне
- Регистрируется как Master в Repmgr
- Запускает — демон от Repmgr для мониторинга репликации (о нем тоже позже)
-
Для Standby:
- Клонирует Primary сервер с помощью Repmgr (между прочим со всеми конфигами, так как просто копирует директорию)
- Конфигурирует Repmgr
- Запускает Postgresql сервис в фоне — после клонирования сервис вменяемо осознает, что является standby и покорно следует за Primary
- Регистрируется как Slave в Repmgr
- Запускает
Для всех этих операций важна последовательность, и посему в коде напиханы . Знаю — не хорошо, но так удобно конфигурировать задержки через ENV переменные, когда нужно разом стартануть все контейнеры (например через )
Все переменные к этому образу описаны в .
Вся разница первого и второго слоя Standby сервисов в том, что для второго мастером является любой сервис из первого слоя, а не Primary. Не забываем, что второй эшелон должен стартовать после первого с задержкой во времени.
Split-brain и выборы нового лидера в кластере
Split brain — ситуация, в которой разные сегменты кластера могут создать/избрать нового Master-a и думать, что проблема решена.
Это одна, но далеко не единственная проблема, которую мне помог решить Repmgr.
По сути это менеджер, который умеет делать следующее:
- Клонировать Master (master — в терминах Repmgr) и автоматически настоить вновьрожденный Slave
- Помочь реанимировать кластер при смерти Master-а.
- В автоматическом или ручном режиме Repmgr может избрать нового Master-а и перенастроить все Slave сервисы следовать за новым лидером.
- Выводить из кластера узлы
- Мониторить здоровье кластера
- Выполнять команды при
В нашем случае на помощь приходит который запускается основным процессом в контейнере и следит за целостностью кластера. При ситуации, когда пропадает доступ к Master серверу, Repmgr пытается проанализировать текущую структуру кластера и принять решение о том, кто станет следующим Master-ом. Естественно Repmgr достаточно умен чтобы не создать ситуацию Split Brain и выбрать единственно правильного Master-а.
Pgpool-II — swiming pool of connections
Последняя часть системы — Pgpool. Как я писал в разделе о плохих решениях, сервис все же делает свою работу:
- Балансирует нагрузку между всеми уздами кластера
- Храннит дескрипторы соединений для оптимизации скорости доступа к БД
- При нашем случае Streaming Replication — автоматически находит Master и использует его для запросов на запись.
Как исход, у меня получился довольно простой Docker Image, который при старте конфигурирует себя на работу с набором узлов и пользователей, у которых будет возможность проходить md5 авторизацию сквозь Pgpool ()
Очень часто возникает задача избавиться от единой точки отказа, и в нашем случае — этой точкой является pgpool сервис, который проксирует все запросы и может стать самым слабым звеном на пути доступа к данным.
К счастью, в этом случае нашу проблему решает k8s и позволяет сделать столько репликаций сервиса сколько нужно.
В примере для Kubernetes к сожалению этого нет, но если вы знакомы c тем как работает Replication Controller и/или Deployment, то провернуть вышеописанное вам не составит труда.
Список источников
- habr.com
- postgrespro.ru