В ответ на вопросы производительности, которые часто возникают во время использования, я даю следующие три набора лучших практик:
❄ Если требования к генерации идентификатора не превышают 5 Вт/с, нет необходимости изменять какие-либо параметры конфигурации.
❄ Если она превышает 5 Вт шт./с и меньше 50 Вт шт./с, рекомендуется изменить: SeqBitLength=10.
❄ Если она превышает 50 Вт бит/с и близка к 500 Вт бит/с, рекомендуется изменить: SeqBitLength=12.
Таким образом, увеличение SeqBitLength приведет к повышению производительности, но генерируемые идентификаторы будут длиннее.
❄ Это оптимизированный алгоритм снежинок (снос снежинок), который генерирует более короткие и быстрые идентификаторы.
❄ Поддерживает автоматическое расширение контейнерных сред, таких как k8s (автоматическая регистрация WorkerId), и может генерировать уникальный цифровой идентификатор в автономной или распределенной среде.
❄ Встроенная поддержка C#/Java/Go/C/Rust/Python/Node.js/PHP (расширение C)/SQL/ и других языков, а также обеспечивает многопоточный безопасный вызов динамических библиотек (FFI).
❄ Совместимость со всеми алгоритмами снежинки (режим сегмента номера или классический режим, крупные или мелкие производители), в будущем вы можете сделать любое обновление или переключение.
❄ Это наиболее полный инструмент создания идентификаторов Snowflake ID в истории компьютеров. 【По состоянию на август 2022 г.】
? Как архитектор, вы хотите решить проблему уникальных первичных ключей в базе данных, особенно в распределенной системе с несколькими базами данных.
? Вы хотите, чтобы первичный ключ таблицы данных занимал минимум места для хранения, индексировался быстрее, а также быстрее выполнял выбор, вставку и обновление.
? Следует учитывать, что при разделении баз данных и таблиц (объединении баз данных и таблиц) значение первичного ключа может использоваться напрямую и может отражать бизнес-тайминг.
? Если такое значение первичного ключа слишком длинное и превышает максимальное значение внешнего типа js Number, тип Long необходимо преобразовать в тип String, и вы почувствуете небольшое разочарование.
? Хотя Guid может автоматически увеличиваться, он занимает много места и скорость индексирования низкая. Вы не хотите его использовать.
? Может быть более 50 экземпляров приложений, и каждый одновременный запрос может достигать 10 Вт/с.
? Для развертывания приложений в контейнерной среде поддерживается горизонтальная репликация и автоматическое расширение.
? Вы не хотите полагаться на операцию автоматического приращения Redis для получения непрерывных идентификаторов первичного ключа, поскольку непрерывные идентификаторы создают риски для безопасности бизнес-данных.
? Вы хотите, чтобы система работала более 100 лет?
Сгенерированный идентификатор слишком длинный.
Объема мгновенного параллелизма недостаточно.
Проблема обратного набора времени не может быть решена.
Последополнительное создание идентификатора предварительного заказа не поддерживается.
Может полагаться на внешние системы хранения.
✔ Целые числа, монотонно увеличивающиеся во времени (не обязательно непрерывные), более короткие по длине и не превышающие максимального значения типа js Number за 50 лет. (конфигурация по умолчанию)
✔ Быстрее, в 2–5 раз быстрее, чем традиционный алгоритм снежинки, 500 000 могут быть сгенерированы за 0,1 секунды (на основе низковольтного i7 8-го поколения).
✔ Поддержка обработки обратного вызова времени. Например, если время сервера установлено на 1 секунду назад, этот алгоритм может автоматически адаптироваться для генерации уникального идентификатора для критического времени.
✔Поддерживает вставку новых идентификаторов вручную. Когда бизнесу необходимо генерировать новые идентификаторы в исторические сроки, зарезервированные биты этого алгоритма могут генерировать 5000 идентификаторов в секунду.
✔ Не зависит от внешнего кеша или базы данных. (Динамическая библиотека, которая автоматически регистрирует WorkerId в среде k8s, использует redis)
✔Базовые функции, готовые к использованию «из коробки», не требуются файлы конфигурации, подключения к базе данных и т. д.
(Параметры: 10-битная автовозрастающая последовательность, 1000 максимальных значений дрейфа)
Непрерывные запросы | 5К | 5 Вт | 50 Вт |
---|---|---|---|
Традиционный алгоритм снежинки | 0,0045 с | 0,053 с | 0,556 с |
Алгоритм снежного заноса | 0,0015 с | 0,012 с | 0,113 с |
? Максимальная производительность: 500 Вт/с ~ 3000 Вт/с. (Все данные испытаний рассчитаны на основе низковольтного i7 8-го поколения)
? Когда системное время восстанавливается, алгоритм использует зарезервированный порядковый номер прошлого временного ряда для генерации нового идентификатора.
? Идентификатор, сгенерированный обратным вызовом, по умолчанию размещается первым, но его также можно настроить так, чтобы он располагался позже.
? Разрешить время вернуться к заданной базе этого алгоритма (параметры можно регулировать).
? Идентификатор, сгенерированный этим алгоритмом, является целым числом (занимает до 8 байт пространства). Ниже приведен идентификатор, сгенерированный на основе конфигурации по умолчанию:
129053495681099 (运行1年,长度:15)
387750301904971 (运行3年,长度:15)
646093214093387 (运行5年,长度:15)
1292658282840139 (运行10年,长度:16)
9007199254740992 (运行70年,达到 js Number 最大值,长度:16)
165399880288699493 (运行1000年,等同普通雪花算法运行1年,长度:18)
? Значение идентификатора, генерируемое этим алгоритмом, составляет 1–10 % от максимального значения js Number, что составляет одну тысячную значения обычного алгоритма снежинки, но скорость генерации выше, чем у обычного алгоритма снежинки.
Максимальное значение типа номера js: 9007199254740992. Этому алгоритму может потребоваться 70 лет, чтобы достичь максимального значения js Number при сохранении производительности параллелизма (5 Вт +/0,01 с) и максимум 64 WorkerIds (6 бит).
? 每增加 1位 WorkerIdBitLength 或 SeqBitLength,生成的ID数字值将会乘以2(基础长度可参考前一节“ID示例”),反之则除以2。
Объяснение того, как долго его можно использовать, относится к случаям, когда сгенерированный идентификационный номер может превысить максимальное значение long (64 бита со знаком, 8 байтов).
• В конфигурации по умолчанию доступно 71 000 уникальных идентификаторов.
? При поддержке 1024 рабочих узлов идентификаторы доступны в течение 4480 лет без дублирования.
? При поддержке 4096 рабочих узлов идентификаторы доступны в течение 1120 лет без дублирования.
❄ WorkerIdBitLength , битовая длина машинного кода, определяет максимальное значение WorkerId, значение по умолчанию — 6 , а диапазон значений — [1, 19]. Фактически, в некоторых языках для получения используется беззнаковый тип ushort (uint16). этот параметр, поэтому максимальное значение равно 16. Если используется знак короткого типа (int16), максимальное значение равно 15.
❄ WorkerId , машинный код, самый важный параметр , нет значения по умолчанию, должен быть глобально уникальным (или уникальным в пределах одного DataCenterId), должен задаваться программно , условие по умолчанию (WorkerIdBitLength принимает значение по умолчанию), максимальное значение — 63, теоретическое максимальное значение — 2^WorkerIdBitLength -1 (разные языки реализации могут быть ограничены 65535 или 32767, принцип тот же, что и правило WorkerIdBitLength). Оно не может быть одинаковым на разных компьютерах или в разных экземплярах приложения. Это значение можно настроить через приложение или получить его, вызвав внешнюю службу. В ответ на необходимость автоматической регистрации WorkerId этот алгоритм предоставляет реализацию по умолчанию: автоматическую регистрацию динамической библиотеки WorkerId через Redis, подробности см. в разделе «ИнструментыAutoRegisterWorkerId».
Особое примечание . Если на сервере развертывается несколько независимых служб, вам необходимо указать разные WorkerId для каждой службы.
❄ SeqBitLength , длина последовательности в битах, значение по умолчанию 6 , диапазон значений [3, 21] (рекомендуется не менее 4), определяет количество идентификаторов, генерируемых за миллисекунду. Если количество запросов в секунду не превышает 5 Вт, просто оставьте значение по умолчанию 6, если оно превышает 5 Вт и не превышает 50 Вт, рекомендуется назначить значение 10 или больше и т. д. Требование правила: WorkerIdBitLength + SeqBitLength не превышает 22.
❄ MinSeqNumber , минимальный порядковый номер, значение по умолчанию 5, диапазон значений [5, MaxSeqNumber], первые 5 порядковых номеров в миллисекунду соответствуют числам 0–4 и являются зарезервированными битами, из которых 1–4 являются соответствующими зарезервированными битами для обратного набора времени. , 0 — зарезервированный бит для новых значений вручную.
❄ MaxSeqNumber , максимальный порядковый номер, диапазон настройки: [MinSeqNumber, 2^SeqBitLength-1], значение по умолчанию — 0, реальный максимальный порядковый номер — максимальное значение (2^SeqBitLength-1), если он не равен 0. , это реальный максимальный порядковый номер, который обычно не нужно устанавливать, если только несколько компьютеров не используют WorkerId для генерации идентификаторов в сегментах (в этом случае минимальный порядковый номер должен быть установлен правильно).
❄ BaseTime , базовое время (также известное как: время базовой точки, время начала, время эпохи), имеет значение по умолчанию (2020), представляет собой временную метку в миллисекундах (целое число, .NET — тип DatetTime), его функция: использовать при создании идентификатора Разница (в миллисекундах) между системным временем и базовым временем используется в качестве временной метки для создания идентификатора. Обычно нет необходимости устанавливать базовое время. Если вы считаете, что значение по умолчанию слишком старое, вы можете его сбросить. Однако обратите внимание, что лучше не менять это значение в будущем.
Во второй версии планируется добавить параметры:
❄ DataCenterId , идентификатор центра обработки данных (идентификатор компьютерного зала, по умолчанию 0). Убедитесь, что он глобально уникален.
❄ DataCenterIdBitLength — длина идентификатора центра обработки данных (по умолчанию 0).
❄ TimestampType , тип метки времени (0 миллисекунд, 1 секунда), по умолчанию 0.
1️⃣ Звонок в одноэлементном режиме. Этот алгоритм использует один поток для генерации идентификаторов, а вызовы от нескольких сторон будут взаимоисключающими. В том же экземпляре приложения вызывающая сторона использует многопоточность (или параллель) для вызова этого алгоритма, что не увеличивает скорость вывода идентификатора.
2️⃣ Укажите уникальный WorkerId. Глобальная уникальность WorkerId должна обеспечиваться внешней системой и присваиваться входному параметру этого алгоритма.
3️⃣ Используйте разные WorkerId при развертывании нескольких экземпляров на одном компьютере. Не все реализации поддерживают одновременную уникальность между процессами. На всякий случай при развертывании нескольких экземпляров приложения на одном хосте убедитесь, что каждый WorkerId уникален.
4️⃣ Обработка исключений. Алгоритм будет генерировать все исключения, и внешняя система должна перехватывать исключения и правильно их обрабатывать, чтобы избежать более серьезного сбоя системы.
5️⃣ Внимательно изучите определение IdGeneratorOptions, которое будет полезно для интеграции и использования этого алгоритма.
6️⃣ Используйте алгоритм снежного заноса. Хотя код содержит определение традиционного алгоритма снежинки, и вы можете указать (Метод=2) в точке входа, чтобы включить традиционный алгоритм, все равно рекомендуется использовать алгоритм сноса снежинок (Метод=1, значение по умолчанию). В конце концов, он имеет лучшую растяжимость и более высокую производительность.
7️⃣ Не изменяйте основной алгоритм. Этот алгоритм имеет множество внутренних параметров и сложную логику. Если вы не освоили основную логику, не изменяйте основной код и не используйте его в производственной среде, если он не был проверен с помощью большого количества тщательных и научных тестов.
8. Политики конфигурации внутри домена приложения одинаковы. Если система работает в течение определенного периода времени и проекту необходимо перейти от программного указания WorkerId к автоматической регистрации WorkerId, убедитесь, что все экземпляры, используемые в одном домене приложения, используют согласованную стратегию настройки. Это касается не только WorkerId. , но также включает другие параметры конфигурации.
9️⃣ Хорошо управляйте временем сервера. Алгоритм «Снежинка» зависит от системного времени. Не изменяйте вручную время операционной системы на большую величину. Если вам необходимо выполнить настройку, не забудьте убедиться, что системное время при повторном запуске службы превышает время ее последнего закрытия. (Примечание. Небольшие изменения системного времени, вызванные синхронизацией времени или обратным вызовом на мировом или сетевом уровне, не влияют на этот алгоритм)
Изменения конфигурации относятся к корректировке рабочих параметров (свойств объекта IdGeneratorOptions) после того, как система проработала в течение определенного периода времени. Обратите внимание:
? 1. Первый принцип: BaseTime может быть только старше (дальше настоящего), чтобы сгенерированное значение идентификатора было больше, чем историческое максимальное значение, гарантируя отсутствие перекрытия во времени и создание повторяющихся идентификаторов. [ Не рекомендуется настраивать BaseTime после запуска системы]
? 2. Увеличение WorkerIdBitLength или SeqBitLength в любое время разрешено, но операцию «уменьшения» следует использовать с осторожностью, поскольку это может привести к тому, что идентификатор, сгенерированный в будущем, будет таким же, как и в старой конфигурации. [Разрешить увеличение любого значения xxxBitLength после запуска системы]
? 3. Если одно из WorkerIdBitLength или SeqBitLength необходимо уменьшить, должно выполняться условие: сумма двух новых xxxBitLength должна быть больше суммы старых значений. [Сужение любого значения BitLength после запуска не рекомендуется ]
? 4. Вышеупомянутые три правила не контролируются логически в этом алгоритме. Пользователи должны вносить изменения в конфигурацию после подтверждения того, что новая конфигурация соответствует требованиям.
Генератор уникальных идентификаторов использует WorkerId. Когда бизнес-службам требуется горизонтальная и неизбирательная репликация (автоматическое расширение), для этого требуется возможность автоматически регистрировать глобально уникальный WorkerId перед созданием уникального идентификатора.
? Этот алгоритм предоставляет динамическую библиотеку с открытым исходным кодом (реализованную на языке Go), которая может автоматически регистрировать WorkerId через Redis в контейнерных средах, таких как k8s.
? Регистрация WorkerId через Redis — не единственный способ. Вы также можете разработать службу централизованной настройки. При запуске каждой службы конечной точки уникальный WorkerId получается через центральную службу.
? Конечно, если ваш сервис не нуждается в автоматическом расширении, вам не нужно автоматически прописывать WorkerId, а задавать для них глобально уникальные значения.
? Существует множество методов, таких как: разработка централизованной службы генерации идентификаторов, которая генерирует используемые идентификаторы для каждой службы конечной точки (отдельной или пакетной).
Ссылка на изображение: https://github.com/yitter/IdGenerator/blob/master/Tools/AutoRegisterWorkerId/regprocess.jpg
Путь к исходному коду:/Go/source/regworkerid/reghelper.go
Ссылка для скачивания: https://github.com/yitter/IdGenerator/releases/download/v1.3.3/workeridgo_lib_v1.3.3.zip
// 注册一个 WorkerId,会先注销所有本机已注册的记录
// address: Redis连接地址,单机模式示例:127.0.0.1:6379,哨兵/集群模式示例:127.0.0.1:26380,127.0.0.1:26381,127.0.0.1:26382
// password: Redis连接密码
// db: Redis指定存储库,示例:1
// sentinelMasterName: Redis 哨兵模式下的服务名称,示例:mymaster,非哨兵模式传入空字符串即可
// minWorkerId: WorkerId 最小值,示例:30
// maxWorkerId: WorkerId 最大值,示例:63
// lifeTimeSeconds: WorkerId缓存时长(秒,3的倍数),推荐值15
extern GoInt32 RegisterOne(char* server, char* password, GoInt32 db, char* sentinelMasterName, GoInt32 minWorkerId, GoInt32 maxWorkerId, GoInt32 lifeTimeSeconds);
// 注销本机已注册的 WorkerId
extern void UnRegister();
язык | github |
---|---|
?С# | Посмотреть пример |
?Ява | Посмотреть пример |
?Идти | Посмотреть пример |
? | Посмотреть пример |
?Питон | Посмотреть пример |
?С | Посмотреть пример |
? C (расширение PHP) | Посмотреть пример |
? Делфи (Паскаль) | Посмотреть пример |
? | Посмотреть пример |
?Машинопись | Посмотреть пример |
? В | Посмотреть пример |
?Д | Посмотреть пример |
Адрес с открытым исходным кодом: https://github.com/yitter/IdGenerator.
Группа QQ: 646049993