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。

我的另一个问题是关于查询分片。据我了解,他们使用映射到实际服务器的逻辑分片。如果他们决定将一个逻辑分片映射到一个新的服务器,这意味着他们必须同时查询两个服务器来聚合结果,因为在他们为同一个逻辑分片分配一个新服务器之前,一些数据被添加到较旧的服务器。我只是想知道是否有更好的方法来使用逻辑分片,并且可以选择查询数据所在的单个服务器,而不是查询属于该逻辑分片的所有服务器?

谢谢。

4

6 回答 6

1

从代码看起来你只需要复制序列,你可以通过在 MySQL 中使用 AUTO_INCREMENT 创建表并使用它来生成标识号来完成。

于 2012-10-22T13:14:14.680 回答
1

这是 postgres 等价的

指定TABLE_SCHEMAMASKTABLE以下

我正在创建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

用 MySQL 存储过程实现完全相同的 id 生成逻辑是不可能的。但是,这可以使用MySQL UDF来完成。

这是一个 UDF,它通过一些更改重新创建 instagrams id 生成器。将其修改为与 instagram id 生成器完全相同的工作将涉及更新 MAX_* 常量和 next_shard_id 和 shard_id_to_ms 中的位移逻辑。

于 2014-10-15T21:17:36.287 回答
0

ScaleBase,我们找到了一种很好的方式来支持自动增量,通过变量: SET @@auto_increment_increment=4;.

只要确保每个分片都有一个起始偏移量,你就可以自由离开了。它直接,简单,与现有的 MySQL 和其他东西兼容。

于 2012-10-22T15:54:29.273 回答
0

我对我编写的转换例程有疑问,但它似乎确实有效!

AUTO_INCREMENT 可以在 MySQL 的 BEFORE TRIGGER 中安全使用吗

一旦我得到答案,我也会更新这个答案。

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

关于另一个问题,一个逻辑分片的所有数据一次只存在于生产中的一台服务器上(不考虑复制)。当他们的现有服务器容量不足时,他们会将每个服务器中的数据复制到跟随者,并且当新服务器准备好时(此时原始服务器和新服务器都包含特定逻辑分片的所有数据),他们开始从新服务器读取一半分片的所有数据,而另一半则留在原始服务器中。有关说明,请参见例如http://www.craigkerstiens.com/2012/11/30/sharding-your-database/

于 2014-05-09T09:47:21.090 回答