ホームページ php教程 php手册 分散システム向けの固有 ID 生成ソリューションの概要

分散システム向けの固有 ID 生成ソリューションの概要

Sep 14, 2018 pm 01:39 PM
配布された

一意のシステム ID は、システムを設計するときによく遭遇する問題であり、よくこの問題に悩まされます。 ID を生成するには、さまざまなシナリオ、ニーズ、パフォーマンス要件に適応するさまざまな方法があります。したがって、一部のより複雑なシステムには複数の ID 生成戦略があります。ここでは、一般的な ID 生成戦略をいくつか示します。

1. データベースの自己増加シーケンスまたはフィールド

最も一般的な方法。データベースを使用すると、データベース全体が固有になります。

利点:

  1. シンプルで便利なコードと許容可能なパフォーマンス。

  2. #数値 ID は自然に並べ替えられるため、並べ替えが必要なページングや結果に役立ちます。

#欠点:

  1. # データベースの移行時や複数のデータベース バージョンの場合、データベースの構文と実装が異なります。サポートされている 処理が必要です。

  2. #単一データベース、読み取り/書き込み分離、または 1 つのマスターと複数のスレーブの場合、生成できるマスター データベースは 1 つだけです。単一障害点が発生するリスクがあります。

  3. #パフォーマンスが要件を満たさない場合、拡張は困難です。

  4. 複数のシステムを統合する必要がある場合、またはデータ移行が関係する場合は、かなりの時間がかかります。痛い。

  5. #テーブルやデータベースを分割するときに問題が発生します。
  6. 最適化計画:

    メイン データベースの単一ポイントの場合、複数のマスター データベースがある場合、各マスターライブラリによって設定された開始番号は異なりますが、ステップ サイズは同じであり、これがマスターの数になる可能性があります。例: Master1 は 1、4、7、10 を生成し、Master2 は 2、5、8、11 を生成し、Master3 は 3、6、9、12 を生成します。これにより、クラスター内で一意の ID を効果的に生成でき、ID 生成データベース操作の負荷も大幅に軽減できます。
  1. 2. UUID 共通メソッド。

これはデータベースまたはプログラムを使用して生成でき、一般に世界で唯一のものです。

利点:

    シンプルで便利なコード。
  1. #ID 生成のパフォーマンスは非常に優れており、基本的にパフォーマンスの問題は発生しません。
  2. データ移行、システムデータ結合、データベースの場合は世界で唯一。変化しても、それをスムーズに受け止めることができます。
  3. 欠点:

並べ替えがないため、傾向が増加することは保証できません。
  1. UUID は文字列を使用して保存されることが多く、クエリ効率は比較的低くなります。
  2. 大規模なデータベースの場合、ストレージ容量を考慮する必要があります。額。
  3. #大量のデータを転送する

  4. # は読み取れません。

  5. 3. Redis による ID の生成

    データベースを使用して ID を生成するパフォーマンスが十分でない場合は、Redis を使用して ID を生成することもできます。 IDを生成します。これは主にシングルスレッドである Redis に依存しているため、グローバルに一意な ID の生成にも使用できます。これは、Redis のアトミック操作 INCR および INCRBY を使用して実現できます。
Redis クラスターを使用すると、より高いスループットを得ることができます。クラスター内に 5 つの Redis があるとします。各 Redis の値はそれぞれ 1、2、3、4、5 に初期化でき、ステップ サイズはすべて 5 になります。各 Redis によって生成される ID は次のとおりです:

A: 1,6,11,16,21 B: 2,7,12,17,22 C: 3,8,13,18,23 D: 4 , 9,14,19,24 E: 5,10,15,20,25

これは、どのマシンにロードされるかによって決まります。将来的に変更するのは困難です。ただし、基本的には 3 ~ 5 台のサーバーでサーバーのニーズを満たすことができ、すべてのサーバーで異なる ID を取得できます。ただし、ステップ サイズと初期値は事前に必要です。 Redis クラスターを使用すると、単一障害点の問題も解決できます。

また、Redis を使用して毎日 0 から始まるシリアル番号を生成する方が適しています。たとえば、注文番号 = 日付の場合、番号はその日に自動的に増加します。毎日 Redis でキーを生成し、蓄積に INCR を使用できます。

利点:

## はデータベースに依存せず、柔軟で便利で、データベースよりもパフォーマンスが優れています。

  1. #数値 ID は自然に並べ替えられるため、並べ替えが必要なページングや結果に役立ちます。
  2. 欠点:

    システムに Redis がない場合は、新しいコンポーネントを導入する必要があり、システムの複雑さ。

  1. #コーディングと構成に必要な作業負荷は比較的大きくなります。

  2. 4. Twitter のスノーフレーク アルゴリズム

    Snowflake は Twitter のオープンソースの分散 ID 生成アルゴリズムであり、結果は長い ID になります。中心となるアイデアは、ミリ秒数として 41 ビット、マシン ID として 10 ビット (5 ビットがデータセンター、5 ビットがマシン ID)、ミリ秒以内のシリアル番号として 12 ビット (つまり、各ノードが4096 ID を生成します)、最後には符号ビットがあり、常に 0 になります。特定の実装コードは、https://github.com/twitter/snowflake

    で見つけることができます。
    public class IdWorker {
    // ==============================Fields===========================================
    /** 开始时间截 (2015-01-01) */
    private final long twepoch = 1420041600000L;
    
    /** 机器id所占的位数 */
    private final long workerIdBits = 5L;
    
    /** 数据标识id所占的位数 */
    private final long datacenterIdBits = 5L;
    
    /** 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) */
    private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
    
    /** 支持的最大数据标识id,结果是31 */
    private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
    
    /** 序列在id中占的位数 */
    private final long sequenceBits = 12L;
    
    /** 机器ID向左移12位 */
    private final long workerIdShift = sequenceBits;
    
    /** 数据标识id向左移17位(12+5) */
    private final long datacenterIdShift = sequenceBits + workerIdBits;
    
    /** 时间截向左移22位(5+5+12) */
    private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
    
    /** 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095) */
    private final long sequenceMask = -1L ^ (-1L << sequenceBits);
    
    /** 工作机器ID(0~31) */
    private long workerId;
    
    /** 数据中心ID(0~31) */
    private long datacenterId;
    
    /** 毫秒内序列(0~4095) */
    private long sequence = 0L;
    
    /** 上次生成ID的时间截 */
    private long lastTimestamp = -1L;
    
    //==============================Constructors=====================================
    /**
     * 构造函数
     * @param workerId 工作ID (0~31)
     * @param datacenterId 数据中心ID (0~31)
     */
    public IdWorker(long workerId, long datacenterId) {
        if (workerId > maxWorkerId || workerId < 0) {
            throw new IllegalArgumentException(String.format("worker Id can&#39;t be greater than %d or less than 0", maxWorkerId));
        }
        if (datacenterId > maxDatacenterId || datacenterId < 0) {
            throw new IllegalArgumentException(String.format("datacenter Id can&#39;t be greater than %d or less than 0", maxDatacenterId));
        }
        this.workerId = workerId;
        this.datacenterId = datacenterId;
    }
    
    // ==============================Methods==========================================
    /**
     * 获得下一个ID (该方法是线程安全的)
     * @return SnowflakeId
     */
    public synchronized long nextId() {
        long timestamp = timeGen();
    
        //如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常
        if (timestamp < lastTimestamp) {
            throw new RuntimeException(
                    String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
        }
    
        //如果是同一时间生成的,则进行毫秒内序列
        if (lastTimestamp == timestamp) {
            sequence = (sequence + 1) & sequenceMask;
            //毫秒内序列溢出
            if (sequence == 0) {
                //阻塞到下一个毫秒,获得新的时间戳
                timestamp = tilNextMillis(lastTimestamp);
            }
        }
        //时间戳改变,毫秒内序列重置
        else {
            sequence = 0L;
        }
    
        //上次生成ID的时间截
        lastTimestamp = timestamp;
    
        //移位并通过或运算拼到一起组成64位的ID
        return ((timestamp - twepoch) << timestampLeftShift) //
                | (datacenterId << datacenterIdShift) //
                | (workerId << workerIdShift) //
                | sequence;
    }
    
    /**
     * 阻塞到下一个毫秒,直到获得新的时间戳
     * @param lastTimestamp 上次生成ID的时间截
     * @return 当前时间戳
     */
    protected long tilNextMillis(long lastTimestamp) {
        long timestamp = timeGen();
        while (timestamp <= lastTimestamp) {
            timestamp = timeGen();
        }
        return timestamp;
    }
    
    /**
     * 返回以毫秒为单位的当前时间
     * @return 当前时间(毫秒)
     */
    protected long timeGen() {
        return System.currentTimeMillis();
    }
    
    //==============================Test=============================================
    /** 测试 */
    public static void main(String[] args) {
        IdWorker idWorker = new IdWorker(0, 0);
        for (int i = 0; i < 1000; i++) {
            long id = idWorker.nextId();
            System.out.println(Long.toBinaryString(id));
            System.out.println(id);
        }
    }}
    ログイン後にコピー

    スノーフレーク アルゴリズムは、独自のプロジェクトのニーズに応じて変更できます。たとえば、将来のデータ センターの数、各データ センターのマシンの数、統一ミリ秒内に発生する可能性のある同時実行数を推定して、アルゴリズムに必要なビット数を調整します。

    利点:

    1. ## はデータベースに依存せず、柔軟で便利で、データベースよりもパフォーマンスが優れています。

    2. #ID は、単一マシン上で時間に応じて増加します。

    3. 欠点:

    1. は単一マシン上で増分ですが、分散環境が関与するため、各マシンクロック上のクロックは完全に同期することができず、場合によってはグローバルな増分が達成されない状況が発生する可能性があります。

    2. 5. Zookeeper を使用して一意の ID を生成する

    zookeeper は、主に znode データ バージョンを通じてシリアル番号を生成します。32 ビットおよび 64 ビットのデータ バージョン番号を生成できます。顧客 顧客は、このバージョン番号を一意のシリアル番号として使用できます。

    Zookeeper が固有 ID の生成に使用されることはほとんどありません。主な理由は、zookeeper に依存し、複数のステップで API を呼び出すためです。競合が大きい場合は、分散ロックの使用を検討する必要があります。したがって、同時実行性の高い分散環境では、パフォーマンスは理想的ではありません。

    6. MongoDB の ObjectId

    MongoDB の ObjectId は、スノーフレーク アルゴリズムに似ています。これは軽量になるように設計されており、同じ世界的に独自の方法を使用して、さまざまなマシンで簡単に生成できます。 MongoDB は最初から分散データベースとして設計されており、複数のノードを処理することが中心的な要件です。シャーディング環境での生成がはるかに簡単になります。形式は次のとおりです: [src/main/resources/objectId.png] ここに画像の説明を記述します:

    分散システム向けの固有 ID 生成ソリューションの概要最初の 4 バイトは、標準エポックから始まるタイムスタンプです。 、単位は秒です。タイムスタンプは、次の 5 バイトと組み合わされて、第 2 レベルの一意性を提供します。タイムスタンプが最初に来るため、ObjectId はおおよそ挿入された順序で並べ替えられることを意味します。効率化の指標として利用するなどに便利です。これらの 4 バイトは、文書が作成された時刻も意味します。ほとんどのクライアント ライブラリは、ObjectId からこの情報を取得するメソッドを公開します。次の 3 バイトはホストの一意の識別子です。通常はマシンのホスト名のハッシュです。これにより、異なるホストが競合することなく異なる ObjectId を生成することが保証されます。同じマシン上の複数の同時プロセスによって生成される ObjectId が一意であることを確認するために、次の 2 バイトは ObjectId を生成したプロセス識別子 (PID) から取得されます。最初の 9 バイトにより、同じ秒内に異なるマシン上の異なるプロセスによって生成された ObjectId が一意であることが保証されます。最後の 3 バイトは、同じ秒内に同じプロセスによって生成された ObjectId も異なることを保証するために、自動的に増加するカウンターです。各プロセスは、同じ秒内に最大 2563 (16 777 216) 個の異なる ObjectId を持つことができます。

    関連する推奨事項:

    php ニュース リリース管理システム開発例

    PHP 開発の簡単なニュース リリース システム チュートリアル

以上が分散システム向けの固有 ID 生成ソリューションの概要の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Redis を使用して分散データ同期を実現する方法 Redis を使用して分散データ同期を実現する方法 Nov 07, 2023 pm 03:55 PM

Redis を使用して分散データ同期を実現する方法 インターネット テクノロジーの発展とアプリケーション シナリオのますます複雑化に伴い、分散システムの概念がますます広く採用されています。分散システムでは、データの同期は重要な問題です。高性能のインメモリ データベースである Redis は、データの保存に使用できるだけでなく、分散データ同期の実現にも使用できます。分散データ同期には、通常、パブリッシュ/サブスクライブ (パブリッシュ/サブスクライブ) モードとマスター/スレーブ レプリケーション (マスター/スレーブ) の 2 つの共通モードがあります。

MongoDB を使用して分散タスクのスケジューリングと実行を実装した経験を共有する MongoDB を使用して分散タスクのスケジューリングと実行を実装した経験を共有する Nov 02, 2023 am 09:39 AM

MongoDB は、高いパフォーマンス、スケーラビリティ、柔軟性を備えたオープンソースの NoSQL データベースです。分散システムではタスクのスケジューリングと実行が重要な課題となりますが、MongoDB の特性を活用することで、分散タスクのスケジューリングと実行ソリューションを実現できます。 1. 分散タスク スケジューリングの要件分析 分散システムでは、タスク スケジューリングは、実行のためにタスクをさまざまなノードに割り当てるプロセスです。一般的なタスク スケジューリング要件は次のとおりです。 1. タスク リクエストの分散: タスク リクエストを利用可能な実行ノードに送信します。

Redis が分散セッション管理を実装する方法 Redis が分散セッション管理を実装する方法 Nov 07, 2023 am 11:10 AM

Redis が分散セッション管理を実装する方法には、特定のコード サンプルが必要です。分散セッション管理は、今日インターネット上で注目されているトピックの 1 つです。高い同時実行性と大量のデータに直面して、従来のセッション管理方法は徐々に不十分になりつつあります。 Redis は、高性能のキー/値データベースとして、分散セッション管理ソリューションを提供します。この記事では、Redis を使用して分散セッション管理を実装する方法と、具体的なコード例を紹介します。 1. 分散セッション ストレージとしての Redis の概要 従来のセッション管理方法は、セッション情報を保存することです。

Swoole を使用して分散スケジュールされたタスクのスケジューリングを実装する方法 Swoole を使用して分散スケジュールされたタスクのスケジューリングを実装する方法 Nov 07, 2023 am 11:04 AM

Swoole を使用して分散スケジュールされたタスク スケジューリングを実装する方法 はじめに: 従来の PHP 開発では、スケジュールされたタスク スケジューリングを実装するために cron を使用することがよくありますが、cron は単一サーバー上でのみタスクを実行でき、同時実行性の高いシナリオには対応できません。 Swoole は、PHP をベースとした高性能の非同期同時実行フレームワークで、完全なネットワーク通信機能とマルチプロセスのサポートを提供し、分散スケジュールされたタスクのスケジューリングを簡単に実装できます。この記事では、Swooleを使用して分散スケジュールされたタスクのスケジューリングを実装する方法を紹介します。

Java開発実践体験共有:分散ログ収集機能の構築 Java開発実践体験共有:分散ログ収集機能の構築 Nov 20, 2023 pm 01:17 PM

Java開発の実践経験の共有:分散ログ収集機能の構築 はじめに: インターネットの急速な発展と大規模データの出現に伴い、分散システムの適用はますます広がっています。分散システムでは、ログの収集と分析は非常に重要な部分です。この記事では、Java 開発で分散ログ収集機能を構築した経験を共有し、読者の参考になれば幸いです。 1. 背景の紹介 分散システムでは、各ノードが大量のログ情報を生成します。これらのログ情報は、システム パフォーマンスの監視、トラブルシューティング、データ分析に役立ちます。

Redis を使用して分散タスク スケジューリングを実装する Redis を使用して分散タスク スケジューリングを実装する Nov 07, 2023 am 08:15 AM

Redis を使用した分散タスク スケジューリングの実装 ビジネスの拡大とシステムの開発に伴い、多くの企業では、タスクを複数のノードで同時に実行できるように分散タスク スケジューリングを実装する必要があります。これにより、システムの安定性と可用性が向上します。システム。 Redis は高性能メモリ データ ストレージ製品として、分散、高可用性、高パフォーマンスの特性を備えており、分散タスク スケジューリングの実装に非常に適しています。この記事では、Redis を使用して分散タスク スケジューリングを実装する方法を紹介し、対応するコード例を示します。 1.Redisベース

Redis を使用して分散キャッシュの一貫性を実現する Redis を使用して分散キャッシュの一貫性を実現する Nov 07, 2023 pm 12:05 PM

Redis を使用して分散キャッシュの一貫性を実現する 最新の分散システムでは、キャッシュが非常に重要な役割を果たします。これにより、データベースへのシステム アクセスの頻度が大幅に削減され、システムのパフォーマンスとスループットが向上します。分散システムでは、キャッシュの一貫性を確保するために、複数のノード間のデータ同期の問題を解決する必要があります。この記事では、Redis を使用して分散キャッシュの一貫性を実現する方法と、具体的なコード例を紹介します。 Redis は、永続化、レプリケーション、コレクションをサポートする高性能のキーと値のデータベースです。

Redis を使用して分散メッセージのパブリッシュとサブスクリプションを実装する方法 Redis を使用して分散メッセージのパブリッシュとサブスクリプションを実装する方法 Nov 07, 2023 am 09:39 AM

Redis を使用して分散メッセージのパブリッシュとサブスクリプションを実装する方法 はじめに: 分散システムでは、メッセージのパブリッシュとサブスクリプションは、異なるモジュール間の分離を実現できる一般的な通信モードです。高性能の Key-Value ストレージ システムとして、Redis を使用して分散メッセージのパブリッシュおよびサブスクリプション機能を実装できます。この記事では、Redis を使用してこの機能を実装する方法と、具体的なコード例を紹介します。 1. Redisのパブリッシュ・サブスクライブ機能 Redisのパブリッシュ・サブスクライブ機能は、メッセージキューをベースとした実装方法です。

See all articles