Генерация ID в распределённой системе, часть 2: базы данных



Коротенькое дополнение к предыдущему посту



Каждая вторая статья про id пишет, что генерация через БД подойдёт только пет-проектам или MVP. И для нормальной работы нужен кластер сервисов, чья единственная задача — выдавать другим сервисам id. Отдельный кластер специальных сервисов, не меньше!!1



На большинстве моих проектов ID сущностей создавались через саму БД, и всё было хорошо. В посте покажу несложный приём, который часто используется.



Начнём сначала. Когда в строке с ID пишется строка



ID SERIAL PRIMARY KEY



внутри БД создаётся счётчик, который увеличивается при каждой вставке



Что не так: чтобы id не повторялись, запросы должны проходить через один экземпляр БД. Если сущности создаются часто и объём данных растёт, то такой подход усложняет масштабируемость. Непонятно, как добавить ещё один экземпляр БД



Но если данных не очень много, то вариант отличный.



Следующий шаг: вся последовательность равномерно делится между экземплярами БД.



Например, для 3 экземпляров БД (шардов) шаг будет равен трём и формируются такие id:

▫️ В первом шарде: 1, 4, 7, 10, …

▫️ Во втором: 2, 5, 8, 11, …

▫️ В третьем: 3, 6, 9, 12, …



Скрипт для второго шарда выглядит так:



CREATE SEQUENCE userIdGen INCREMENT BY 3 START WITH 2;  



Нагрузка на БД ниже по сравнению с первым вариантом

Несложно мигрировать с первого варианта на второй

😐 Не все БД поддерживают инкремент с шагом

😐 Для каждого экземпляра БД нужен свой скрипт

😐 Менять количество экземпляров БД — очень волнительный процесс



Разумеется, подход с разделением ID не подходит для всех ситуаций. Но этот приём знают не все, поэтому он заслужил отдельный пост:)