作为instagram生成共享和ID

问题描述 投票:1回答:6

我的问题是关于分片环境的ID生成。我正在按照与instagram did相同的步骤生成唯一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。

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

谢谢。

mysql sql sharding
6个回答
1
投票

从代码的外观看,您只需要复制序列,就可以通过在MySQL中使用AUTO_INCREMENT创建表并将其用于生成标识号来实现。


0
投票

ScaleBase,我们找到了一种很好的方法,可以通过变量为自动增量提供支持:SET @@auto_increment_increment=4;

只需确保每个分片都有一个起始偏移量,您就可以自由进行。它简单,直接,并与现有的MySQL和其他东西兼容。


0
投票

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


0
投票

我对我编写的转换例程有疑问,但是它确实起作用了!

Can AUTO_INCREMENT be safely used in a BEFORE TRIGGER in MySQL

一旦我回答了问题,我也会更新这个答案。

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

0
投票

不可能用MySQL存储过程实现完全相同的ID生成逻辑。但是,可以使用MySQL UDF完成此操作。

Here is a UDF会通过一些更改重新创建instagrams id生成器。对其进行修改以使其完全类似于instagram id生成器,将涉及更新MAX_ *常量以及next_shard_id和shard_id_to_ms中的移位逻辑。


0
投票

这相当于Postgres

指定TABLE_SCHEMA我要创建的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 geneate_next_id()

您可以在触发器中使用它,例如

CREATE TRIGGER trigger_name
BEFORE INSERT ON TableName 
FOR EACH ROW
SET new.id = generate_next_id();
© www.soinside.com 2019 - 2024. All rights reserved.