1

私の質問は、シャード環境のID生成に関するものです。Instagramが一意のIDを生成するために行ったのと同じ手順に従います。MySQLでのこのID生成の実装についていくつか質問があります。

これがIDの生成方法です(これはPGQLストアドプロシージャです)。

CREATE OR REPLACE FUNCTION insta5.next_id(OUT result bigint) AS $$
DECLARE
    our_epoch bigint := 1314220021721;
    seq_id bigint;
    now_millis bigint;
    shard_id int := 5;
BEGIN
    SELECT nextval('insta5.table_id_seq') %% 1024 INTO seq_id;

    SELECT FLOOR(EXTRACT(EPOCH FROM clock_timestamp()) * 1000) INTO now_millis;
    result := (now_millis - our_epoch) << 23;
    result := result | (shard_id << 10);
    result := result | (seq_id);
END;
$$ LANGUAGE PLPGSQL;



CREATE TABLE insta5.our_table (
    "id" bigint NOT NULL DEFAULT insta5.next_id(),
    ...rest of table schema...
)

私の質問は、MySQL(同等のコード)でそれをどのように行うことができるかです。このストアドプロシージャは、次のIDを取得するためにクエリから呼び出す必要があります。

私の他の質問は、シャードのクエリに関するものです。私が理解していることから、彼らは実際のサーバーへのマップである論理シャードを使用しています。論理シャードを新しいサーバーにマップすることにした場合、これは、結果を集約するために2つのサーバーに同時にクエリを実行する必要があることを意味します。これは、同じ論理シャードに新しいサーバーを割り当てる前に、一部のデータがに追加されたためです。古いサーバー。論理シャードを使用し、その論理シャードに属しているすべてのサーバーをクエリするのではなく、データが存在する単一のサーバーをクエリするオプションがあるかどうかを知りたいだけですか?

ありがとう。

4

6 に答える 6

1

コードを見ると、シーケンスを複製する必要があるように見えます。これを行うには、MySQLでAUTO_INCREMENTを使用してテーブルを作成し、それを使用してID番号を生成します。

于 2012-10-22T13:14:14.680 に答える
1

これはpostgresと同等です

以下を指定TABLE_SCHEMAしてくださいMASKTABLE

MASKTABLEダミーの最初のエントリでを作成しています

DELIMITER $$
CREATE OR REPLACE FUNCTION generate_next_id() RETURNS bigint NOT DETERMINISTIC
MAIN: BEGIN
DECLARE our_epoch bigint;
DECLARE seq_id bigint;
DECLARE now_millis bigint;
DECLARE shard_id int;
DECLARE param bigint ;
SET @our_epoch = 1568873367231;
SET @shard_id = 1;
SELECT AUTO_INCREMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA = "SCHEMANAME" AND TABLE_NAME = "MASKTABLE" into @seq_id;
SELECT FLOOR(UNIX_TIMESTAMP()) * 1000 into @now_millis;
SELECT (@now_millis - @our_epoch) << 23 into @param;
SELECT @param | (@shard_id <<10) into @param; 
select @param | (@seq_id) into @param; 
RETURN @param;
END MAIN;$$ 
DELIMITER ;

使用法

select generate_next_id()

あなたはそれをトリガーのように使うことができます

CREATE TRIGGER trigger_name
BEFORE INSERT ON TableName 
FOR EACH ROW
SET new.id = generate_next_id();
于 2019-12-11T09:18:38.533 に答える
0

ScaleBaseでは、変数を介して自動インクリメントのサポートを提供するための優れた方法を見つけました SET @@auto_increment_increment=4;

各シャードに開始オフセットがあり、自由に移動できることを確認してください。ストレートでシンプル、既存のMySQLなどと互換性があります。

于 2012-10-22T15:54:29.273 に答える
0

もう1つの質問に関しては、1つの論理シャードのすべてのデータは、(レプリケーションを考慮せずに)一度に本番環境の1つのサーバーにのみ存在します。既存のサーバーの容量が不足している場合、各サーバーのデータをフォロワーに複製し、新しいサーバーの準備ができたら(この時点で、元のサーバーと新しいサーバーの両方に特定の論理シャードのすべてのデータが含まれます)、新しいサーバーからシャードの半分のすべてのデータの読み取りを開始し、残りの半分は元のサーバーに残ります。説明については、たとえばhttp://www.craigkerstiens.com/2012/11/30/sharding-your-database/を参照してください。

于 2014-05-09T09:47:21.090 に答える
0

私が書いた変換ルーチンについて質問がありますが、それは機能しているようです!

AUTO_INCREMENTをMySQLのBEFORETRIGGERで安全に使用できますか

質問への回答が得られたら、この回答も更新します。

MySQLバージョン:

CREATE TRIGGER shard_insert BEFORE INSERT ON tablename
FOR EACH ROW BEGIN

DECLARE seq_id BIGINT;
DECLARE now_millis BIGINT;
DECLARE our_epoch BIGINT DEFAULT 1314220021721;
DECLARE shard_id INT DEFAULT 1;

SET now_millis = (SELECT UNIX_TIMESTAMP());
SET seq_id = (SELECT AUTO_INCREMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA = "dbname" AND TABLE_NAME =     "tablename");
SET NEW.id = (SELECT ((now_millis - our_epoch) << 23) | (shard_id << 10) | (SELECT MOD(seq_id, 1024)));
END
于 2014-09-05T01:56:51.900 に答える
0

MySQLストアドプロシージャを使用してまったく同じID生成ロジックを実装することはできません。ただし、これはMySQLUDFを使用して実行できます。

これは、いくつかの変更を加えてInstagramIDジェネレーターを再作成するUDFです。Instagram IDジェネレーターとまったく同じように機能するように変更するには、MAX_ *定数と、next_shard_idおよびshard_id_to_msのビットシフトロジックを更新する必要があります。

于 2014-10-15T21:17:36.287 に答える