3

独自のシャーディング ソリューションを構築しています。各 ID は次のように構成されます。

  • シャード ID (小さい整数)
  • テーブル タイプ ID (小さい整数)
  • 増分番号 (big int)

元。00001000010000000015

私は仮想シャードを使用しているので、すべてのシャードを 1 つのサーバーに向けることができます。より多くの容量が必要な場合は、別のサーバーを追加して仮想シャードの一部をそのサーバーに向けるだけで、次回は新しいサーバーにデータが書き込まれます。最初のサーバーではなく、少なくともデータを移動して構成ファイルで変更するまで、読み取りは2つのサーバーに送信されます。

私の問題は、増分番号にあります。それらをユニークにしたい。mysql で特定のテーブルに build int incremental id を使用するのは良くありません。データを別のサーバーに移動する可能性があり、そこにそのテーブルの増分番号を使用する別のデータがある可能性があるため、重複した ID を取得する可能性があるためです。

したがって、私の質問は、その ID を生成する外部テーブルを使用せずに、スケーラブルな方法で一意の ID を生成するにはどうすればよいかということです。Pinterest がこれをどのように解決したかをご紹介します。各テーブルに、シャードごとに異なる値でスキップする増分値を与えることを考えたので、すべてのシャードの増分値は決して同じではありません。

アイデアは、Amazon RDS を使用して独自のシャーディング ソリューションを構築することです。そのため、レプリカは既にそこにあり、スレーブをマスターに昇格させて両方のサーバーのデータを削除し、シャーディング設定ファイルを変更するだけでよいため、バランスを取るのは簡単です。Amazon RDS を使用して簡単にスケーリングできるソリューションを構築することは可能であり、現在他の企業が提供するものよりもはるかに安価になると思います (すでに宿題をしました)。

URL で GUID を使用したくありません。長い数字を使っても構いません。Pinterest、Tumblr、Facebook、その他多くは Guid を使用していないため、それらが解決策であることはわかっています。数値 ID を使用したいことを考慮して、どの解決策が最も効果的かを知りたいだけです。 

ASP.NET C# でアプリケーションを開発しています

4

2 に答える 2

3

一言で言えば、ID を生成するためのアプローチは運命づけられています。一意の ID を生成したい場合は、最終的にボトルネックになる中央サービスが必要です。

また、シャード ID を含めると、悪臭がします。データを新しいシャードに移動するとどうなりますか? すべての ID を更新する必要がありますか?

スケーラブルなソリューションが必要な場合は、UUIDまたは同様のアプローチを検討する必要があります。

または、中央サービスを使用して、呼び出しごとに ID ブロック (たとえば 10,000) を割り当てることもできます。そうすれば、中央サービスを頻繁に叩く必要はありませんが、サービスが失敗した場合、システム全体が停止します.

于 2012-11-09T15:49:49.290 に答える
0

Int16 のシャード ID を使用して、テーブルの作成中に各テーブルに AUTO_INCREMENT 値を設定します。シャード ID を (64 - 16) だけ左にシフトし、1 を追加します。

次の例は ServiceStack.ORMLite ライブラリを使用していますが、純粋な SQL でも同様に実行できます。新しいテーブルを作成する必要がある場合は、既存の各シャードを繰り返し処理し、そのシャードへの DB 接続を開き (接続の詳細はルックアップ テーブルに格納されます)、次のメソッドを呼び出します。

private static void CreateTableInShard<T>(IDbConnection db, bool overwrite = false, short shardId = 0) 
where T : IDataObject, new()
    {
        using (var trans = db.BeginTransaction())
        {
            db.CreateTable<T>(overwrite);

            if (overwrite)
            {
                var tableName = typeof(T).Name;
                var ai = ((long)shardId << 48) + 1;
                var sql = @"ALTER TABLE " + tableName + @"
                          AUTO_INCREMENT " + ai + @" ;";
                db.ExecuteSql(sql);
            }
            trans.Commit();
        }
    }

public interface IDataObject
    {
        long Id { get; set; }
    }

最初は 1 台のマシン上にある論理シャードが多数あります。スケーリングが必要な場合は、シャード全体を別のマシンに移動し、ルックアップ テーブルでシャード ID の接続文字列を変更する必要があります。ただし、その移動後の ID 生成には影響しません。

シャード テーブルを ID でクエリするには、シャード ID を取得して(id >> 48)から、特定のシャードをクエリします。

于 2013-05-29T15:09:15.727 に答える