Версия для печати | оригинал записи

Laravel и ULID

ash — Log-ово Хозяина

11 апреля 2019 19:16
Laravel и ULID
[attachid=599702]

В прошлой статье мы разобрались как в Laravel работать с UUID. Но он не решает всех проблем распределенных систем. Один из новых подходов к генерации уникальных идентификаторов это ULID — Universally Unique Lexicographically Sortable Identifier (универсальный уникальный лексографически сортируемый идентификатор).

[CUT]Сравнение UUID и ULID

Во многих случаях использование UUID неоптимально:
— Это не самый эффективный способ кодирования 128-битной случайности
— UUID v1/v2 непрактичен во многих средах, так как требует доступа к уникальному стабильному MAC-адресу
— UUID v3/v5 требует уникального начального числа и генерирует случайно распределенные идентификаторы, которые могут вызвать фрагментацию во многих структурах данных
— UUID v4 не предоставляет никакой другой информации, кроме случайности, которая может вызвать фрагментацию во многих структурах данных

Вместо этого ULID предлагает:
— 128-битная совместимость с UUID
— 1.21e+24 уникальных ключей в миллисекунду
— Лексикографическая сортировка (т.е. в алфавитном порядке)
— Канонически кодируется как 26-символьная строка, в отличие от 36-символьного UUID
— Использует Crockford Base32 для лучшей эффективности и читаемости (5 бит на символ). Исключены буквы I, L, O, чтобы не путать с цифрами. И буква U, чтобы случайно не сгенерировались непристойность
— Регистронезависимый
— Без специальных символов (безопасный URL)
— Точность метки времени до миллисекунды
— Да просто выглядит эстетичнее, чем UUID :)

Более подробно можно узнать в спецификации ULID


Пример ULID:
Цитирую (PHP)
ulid()
// 01d85pp1982gf6ktvfhq7w78fb

01d85pp198      2gf6ktvfhq7w78fb
  Timestamp          Randomness
    48bits                  80bits


Когда нужен ULID в качестве первичного ключа?

В распределенных системах, когда нужна уверенность, что у идентификаторов не будет коллизий. В высоконагруженной системы, когда автоинкрементный ключ не вариант.
Когда нужна репликация без геммороя (в отличии от int). Когда не хотите показывать пользователю, что получаете информацию об идентификаторе (например: example.com/user/3)


Использование ULID в Laravel

Ставим пакет
Цитирую (HTML)
composer require rorecek/laravel-ulid:^2.0.0

Создаём модель
Цитирую (HTML)
php artisan make:model Product -mcr

Исправляем в миграции модели строку
$table->increments('id');
на
$table->char('id', 26)->primary();

Если связанная модель использует ULID, то тип колонки должен это отображать
Цитирую (PHP)
Schema::create('products', function (Blueprint $table) {
  $table
->char('id', 26)->primary();
  ....
  // связанная модель
  $table
->char('category_id', 26);
  $table
->foreign('category_id')->references('id')->on('categories');
  ....
  $table
->timestamps();
});

В модели укажите использование трейта HasUlid и выставьте флаг incrementing на false.
Цитирую (PHP)
use Illuminate\Database\Eloquent\Model;
use Rorecek\Ulid\HasUlid;

class Product extends Model
{
  use HasUlid;
  ....

  /**
  * Indicates if the IDs are auto-incrementing.
  *
  * @var bool
  */

  public $incrementing = false;

  ....
}

Теперь, когда вы создаете новый экземпляр модели, ULID генерируется автоматически.
Цитирую (PHP)
$item = Product::create();
echo $item
->id;
// 01d85pp1982gf6ktvfhq7w78fb


Автор: Demiurge Ash[/CUT]

Комменты: 0


Demiart © 2019