Модуль ulid | Tarantool
Документация на русском языке
поддерживается сообществом

Модуль ulid

Доступно с версии 3.6.0.

Модуль ulid реализует в Tarantool поддержку ULID – универсального уникального лексикографически сортируемого идентификатора (Universally Unique Lexicographically Sortable Identifier). ULID – это 128-битный идентификатор, состоящий из:

  • 48-битной временной метки в миллисекундах от эпохи Unix;
  • 80-битной случайной (энтропийной) части.

Строки ULID кодируются с использованием Crockford Base32 – компактного и удобного, человекочитаемого алфавита, который исключает визуально неоднозначные символы.

В бинарном виде ULID представлен 16-байтным значением в порядке байт big-endian. Это гарантирует, что лексикографический порядок бинарных ULID совпадает с их хронологическим порядком, как и требует спецификация ULID.

ULID обладают рядом полезных свойств. Такие идентификаторы:

  • лексикографически сортируются по времени создания;
  • полностью помещаются в 26 ASCII-символов;
  • избегают визуально неоднозначных символов, таких как I, L, O или U;
  • имеют 128 бит общей уникальности – как UUID v4.

Tarantool использует монотонный генератор ULID. Это гарантирует, что несколько ULID, созданных в пределах одной миллисекунды, строго возрастают и сохраняют следующий порядок: для любых двух ULID, сгенерированных в одной и той же миллисекунде, созданный позже идентификатор будет больше созданного раньше.

Внутри монотонный генератор хранит последний ULID для текущей миллисекунды и инкрементирует 80-битную случайную часть для каждого следующего идентификатора. Переполнение случайной части возможно только после генерации 2^80 ULID в пределах одной миллисекунды, что практически невозможно в реальных условиях эксплуатации. Однако для строгого соответствия спецификации ULID и чтобы избежать тихого переполнения (wrap-around), реализация детектирует такое переполнение и завершает следующую попытку генерации ошибкой Lua (ULID random component overflow).

Чтобы использовать модуль, выполните команду ниже:

ulid = require('ulid')

Объекты ULID поддерживают полный набор операторов сравнения Lua:

  • == и ~= – равенство и неравенство;
  • < и <= – лексикографическое сравнение;
  • > и >= – лексикографическое сравнение.

Сравнение основано на внутреннем 16-байтном представлении в порядке big-endian и соответствует спецификации ULID: монотонный генератор гарантирует, что порядок сравнения ULID совпадает с порядком их создания, включая одну и ту же миллисекунду.

Сравнение работает как между объектами ULID, так и между объектом ULID и строкой ULID:

  • u1 == u2 сравнивает два объекта ULID напрямую;
  • u1 == "01..." преобразует строку в ULID и сравнивает значения;
  • u1 < "01..." или "01..." < u1 преобразует строковый аргумент в ULID и выполняет лексикографическое сравнение.

Примеры:

tarantool> u1 = ulid.new()
tarantool> u2 = ulid.new()
tarantool> u1 < u2, u1 <= u2, u1 == u2, u1 ~= u2, u1 > u2, u1 >= u2
---
- true
- true
- false
- true
- false
- false
...

tarantool> u = ulid.new()
tarantool> s = u:str()
tarantool> u == s, u < s, u > s
---
- true
- false
- false
...

tarantool> u == "not-a-valid-ulid"
---
- false
...

tarantool> u < "not-a-valid-ulid"
---
- error: '[string "return u < "not-a-valid-ulid""]:1: incorrect value to convert to
    ulid as 2 argument'
...

Ниже приведён список всех функций и элементов модуля ulid.

Имя Назначение
ulid.NULL Объект c нулевым ULID
ulid.ulid()
ulid.bin()
ulid.str()
Сокращения для создания нового значения ULID
ulid.new() Создать новый объект ULID
ulid.fromstr()
ulid.frombin()
ulid_object:bin()
ulid_object:str()
Преобразование между строкой, бинарным видом и объектом ULID
ulid.is_ulid()
ulid_object:isnil()
Проверить тип ULID или нулевое значение
ulid.NULL

Нулевой объект ULID – это идентификатор, содержащий 16 нулевых байт.

Return:нулевое значение ULID
Rtype:cdata

Пример:

tarantool> ulid.NULL
---
- 00000000000000000000000000
...
ulid.new()

Создать новый объект ULID.

Эта функция использует монотонный генератор, описанный в разделе Общие сведения. Несколько ULID, созданных в пределах одной миллисекунды, строго возрастают.

Return:новый объект ULID
Rtype:cdata

Пример:

tarantool> ulid.new()
---
- 06DGE3YNDCM2PPWJT3SKTTRNZR
...
ulid.ulid()

Вызов модуля напрямую эквивалентен вызову ulid.new().

Метод ulid() - это сокращение для ulid.new().

Return:новый объект ULID (то же самое, что ulid.new())
Rtype:cdata

Пример:

tarantool> ulid()
---
- 06DGE41G63GAZ6F0TV4WRSVCCW
...
ulid.str()

Создать новый ULID и вернуть его строковое представление.

Это сокращение для ulid.new():str().

Результат всегда имеет длину 26 символов и кодируется Crockford Base32.

Return:строка ULID
Rtype:строка длиной 26 байт

Пример:

tarantool> ulid.str()
---
- 06DGE480BWZ6H5BKX0KS3Q8S2G
...
ulid.bin()

Создать новый ULID и вернуть его бинарное представление в виде строки длиной 16 байт.

Это сокращение для ulid.new():bin().

Return:ULID в бинарном виде
Rtype:строка длиной 16 байт

Пример:

tarantool> #ulid.bin()
---
- 16
...
ulid.fromstr(ulid_string)

Создать объект ULID из 26-символьной строки.

Входным значением должна быть корректная строка ULID, закодированная Crockford Base32. Если строка некорректна (неверная длина или недопустимые символы), возвращается nil.

Параметры:
  • ulid_string (string) – ULID в виде 26-символьной строки
Return:

преобразованный ULID или nil

Rtype:

cdata или nil

Пример:

tarantool> u = ulid.fromstr('06DGE4FH80PHA28YZVV5Z473T4')
tarantool> u
---
- 06DGE4FH80PHA28YZVV5Z473T4
...
ulid.frombin(ulid_bin)

Создать объект ULID из 16-байтной бинарной строки.

Параметры:
  • ulid_bin (string) – ULID в виде 16-байтной бинарной строки
Return:

преобразованный ULID

Rtype:

cdata

Пример:

tarantool> u1 = ulid.new()
tarantool> b = u1:bin()
tarantool> u2 = ulid.frombin(b)
tarantool> u1 == u2
---
- true
...
ulid.is_ulid(value)

Проверить, является ли переданное значение объектом ULID (cdata).

Параметры:
  • value – значение любого типа
Return:

true, если значение является ULID, иначе false

Rtype:

boolean

Пример:

tarantool> ulid.is_ulid(ulid.new())
---
- true
...

tarantool> ulid.is_ulid("string")
---
- false
...

Объект ULID, который возвращает функции ulid.new(), ulid.fromstr() и ulid.frombin(), предоставляет следующие методы:

ulid_object:bin()

Вернуть ULID в виде 16-байтной бинарной строки.

Return:ULID в бинарном виде
Rtype:строка длиной 16 байт

Пример:

tarantool> u = ulid.new()
tarantool> b = u:bin()
tarantool> #b, b
---
- 16
- "\x01\x9B\a\xAD==\x81u۶-\x93hPa\xAE"
...
ulid_object:str()

Вернуть ULID в виде 26-символьной строки.

Return:ULID в строковом виде
Rtype:строка длиной 26 байт

Объекты ULID также реализуют стандартный Lua-метаметод __tostring. Это означает, что вызов tostring(u) для ULID-объекта u возвращает то же значение, что и u:str(), а ULID-объекты автоматически преобразуются в своё 26-символьное строковое представление, когда это нужно в строковом контексте.

Пример:

tarantool> u = ulid.new()
tarantool> u:str(), tostring(u)
---
- 06DGFBE3J07B7DB5A3JP4WQ9CM
- 06DGFBE3J07B7DB5A3JP4WQ9CM
...
ulid_object:isnil()

Проверить, является ли ULID нулевым (все 16 байт равны нулю).

Return:true для ulid.NULL, иначе false
Rtype:boolean

Пример:

tarantool> ulid.NULL:isnil()
---
- true
...

tarantool> ulid.new():isnil()
---
- false
...

Базовое использование:

tarantool> u_obj = ulid.new()
tarantool> u_str = ulid.str()
tarantool> u_bin = ulid.bin()

tarantool> u_obj, u_str, u_bin
---
- 06DGE6SEZDCFFSFEAJFMC9YQAR
- 06DGE6T0DW0N2N6KMPVZ8SGE4W
- "\x01\x9B\a\eSz8\xBA\xB3\xC5\xCC\xFE\x18\xBB1\xD6"
...

Создание объекта ULID и просмотр его свойств:

tarantool> u = ulid()
---
...

tarantool> #u:bin(), #u:str(), type(u), u:isnil()
---
- 16
- 26
- cdata
- false
...

tarantool> tostring(u) == u:str()
---
- true
...

Преобразование между строковым и бинарным форматами:

tarantool> s = ulid.str()
tarantool> s
---
- 06DGE70CPFDV344XX43687N1SM
...

tarantool> u = ulid.fromstr(s)
tarantool> u:str() == s
---
- true
...

tarantool> b = u:bin()
tarantool> u2 = ulid.frombin(b)
tarantool> u2 == u
---
- true
...

Работа с ulid.NULL:

tarantool> ulid.NULL
---
- 00000000000000000000000000
...

tarantool> ulid.NULL:isnil()
---
- true
...

tarantool> ulid.new():isnil()
---
- false
...

Операторы сравнения:

tarantool> u1 = ulid.new()
tarantool> u2 = ulid.new()
tarantool> u1 < u2
---
- true
...

Проверка типов:

tarantool> u = ulid.new()
tarantool> ulid.is_ulid(u)
---
- true
...

tarantool> ulid.is_ulid("06DGE7RJK8QWJE27X5VVCC5VDW")
---
- false
...

Генерация множества ULID:

tarantool> for i = 1,5 do print(ulid.str()) end
---
06DGE7T8AJD6EDNJ3VQ2ZYB3R4
06DGE7T8AJD6EDNJ3VQ2ZYB3R8
06DGE7T8AJD6EDNJ3VQ2ZYB3RC
06DGE7T8AJD6EDNJ3VQ2ZYB3RG
06DGE7T8AJD6EDNJ3VQ2ZYB3RM
...
Нашли ответ на свой вопрос?
Обратная связь