ホームページ >PHPフレームワーク >Laravel >Laravel分散ユニークIDジェネレータの使用法

Laravel分散ユニークIDジェネレータの使用法

Guanhui
Guanhui転載
2020-06-17 17:20:545326ブラウズ

Laravel分散ユニークIDジェネレータの使用法

アプリケーションでは、データベースの主キーとしてグローバルに一意のIDが必要になることがよくあります。グローバルに一意の ID を生成するにはどうすればよいですか?

まず第一に、グローバルに一意な ID が整数であるか文字列であるかを判断する必要があります。文字列の場合、既存の UUID は要件を完全に満たしているため、追加の作業は必要ありません。欠点は、文字列が ID として多くのスペースを占有し、インデックス作成の効率が整数よりも低いことです。

整数を ID として使用する場合は、範囲が狭すぎるため、最初に 32 ビット int 型を除外し、64 ビットの long 型を使用する必要があります。

整数を ID として使用する場合、自己増加する、グローバルに一意で重複しない ID を生成するにはどうすればよいですか?

オプション 1: 1 から始まるデータベースの自己増加 ID を使用すると、基本的に連続的な増加を実現できます。 Oracle では SEQUENCE、MySQL では主キーに AUTO_INCREMENT が使用でき、グローバルな一意性は保証できませんが、テーブルごとに一意であり、基本的にはニーズを満たします。

データベースの自己増加 ID の欠点は、データを挿入する前に ID を取得できないことです。データの挿入後、取得された ID は一意ですが、トランザクションが送信されるまでは、その ID は有効とは見なされません。一部の双方向参照データを挿入して更新する必要があり、面倒です。

2 番目の方法は、集中 ID ジェネレーター (Redis または ZooKeeper など) を使用するか、データベース テーブルを使用して最後に割り当てられた ID を記録することです。

この方法の最大の欠点は、複雑すぎて、サードパーティのサービスに大きく依存する必要があり、コード構成が煩雑であることです。一般に、ソリューションが複雑になればなるほど、信頼性が低くなり、テストは困難になります。

3 番目の方法は、Twitter の Snowflake アルゴリズムに似ており、各マシンに一意の識別子を割り当て、次にタイムスタンプ ID をインクリメントして、グローバルに一意の ID を実現します。この方法の利点は、ID 生成アルゴリズムが完全にステートレス マシンであり、ネットワーク呼び出しがなく、効率的で信頼性が高いことです。欠点は、一意の識別子が繰り返されると ID の競合が発生することです。

Snowflake アルゴリズムは、41 ビット ミリ秒のタイムスタンプ、10 ビットのマシン ID、および 12 ビットのシリアル番号を使用します。理論的には、最大 1024 台のマシンをサポートして 1 秒あたり 4096000 個のシリアル番号を生成できますが、これは Twitter の規模には十分です。 。

しかし、ほとんどの一般的なアプリケーションでは、1 秒あたり 400 万を超える ID は必要なく、マシンの数も 1024 に達しません。したがって、これを改善して、より短い ID 生成方法を使用できます:

53bitID は、32 ビットの第 2 レベルのタイムスタンプ、16 ビット、および 5 ビットのマシン識別で構成され、32 台のマシンを蓄積し、毎秒 65,000 個のシリアル番号を生成できます。コア コード:

private static synchronized long nextId(long epochSecond) {
    if (epochSecond < lastEpoch) {
        // warning: clock is turn back:
        logger.warn("clock is back: " + epochSecond + " from previous:" + lastEpoch);
        epochSecond = lastEpoch;
    }
    if (lastEpoch != epochSecond) {
        lastEpoch = epochSecond;
        reset();
    }
    offset++;
    long next = offset & MAX_NEXT;
    if (next == 0) {
        logger.warn("maximum id reached in 1 second in epoch: " + epochSecond);
        return nextId(epochSecond + 1);
    }
    return generateId(epochSecond, next, SHARD_ID);}

タイムスタンプ 固定値の減算、このソリューションは 2106 までサポートされます。

1 秒あたり 65,000 のシリアル番号では不十分な場合はどうすればよいでしょうか?それは問題ではありません。タイムスタンプをインクリメントし続けて、次の 1 秒間 65,000 のシーケンス番号を「借用」することができます。

同時に、時刻ダイヤルバックの問題も解決されます。

マシン ID は単純なホスト名スキームを使用します。ホスト名が host-1 と一致する限り、host-2 は設定を行わずにマシン ID を自動的に抽出できます。 。

最後に、なぜ 64 ビット整数ではなく最大 53 ビット整数を使用するのでしょうか?これは、ほとんどのアプリケーションが Web アプリケーションであることを考慮すると、JavaScript を扱う場合、JavaScript でサポートされる整数の最大値は 53 桁であり、これを超えると JavaScript の精度が失われます。したがって、53 ビットの整数は JavaScript で直接読み取ることができますが、53 ビットを超える場合は、JavaScript で正しく処理できるように文字列に変換する必要があり、API インターフェイスがさらに複雑になります。これが、Sina Weibo の API インターフェイスが ididstr の両方を返す理由でもあります。

推奨チュートリアル: "PHP" "Laravel チュートリアル"

以上がLaravel分散ユニークIDジェネレータの使用法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はlearnku.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。