跨分片的增量ID

时间:2012-11-09 15:37:55

标签: mysql sharding

我正在构建自己的分片解决方案。每个ID的构造如下:

  • shard id(small int)
  • 表类型id(小int)
  • 增量数字(大整数)

离。 00001000010000000015

我使用虚拟分片,因此我可以将所有分片指向单个服务器,当我需要更多容量时,我只需添加另一台服务器并将一些虚拟分片指向该服务器,因此下次将写入数据虽然读取将转到两个服务器上,但至少在我移动数据并在配置文件中更改它之前,将它放到新服务器而不是第一个服务器上。

我的问题在于增量号码。我希望那些是独一无二的。在mysql中为特定表使用build int incremental id是不好的,因为我可能会将数据移动到另一个服务器,并且我可能有另一个数据使用其表的增量编号,因此我可能会获得重复的ID。

所以我的问题是如何以可扩展的方式生成唯一ID,而不使用会生成该ID的外部表,因为它不会扩展。我可以向您指出Pinterest如何解决这个可能有帮助的here。我想为每个表赋予一个增量值,该值为每个分片跳过不同的值,因此它们在所有分片上的增量值永远不会相同。

我的想法是使用Amazon RDS构建我自己的分片解决方案,因此副本已经存在,平衡很容易,因为我可以利用提升从属来掌握并只删除两台服务器上的数据并更改我的分片配置文件。我认为有可能构建一个可以使用Amazon RDS轻松扩展的解决方案,它将比其他公司今天提供的产品便宜很多(已完成我的功课)。

我不想在我的网址中使用GUID。我不介意使用长数字。 Pinterest,Tumblr,Facebook和其他许多人都不使用Guid,所以我知道他们是一个解决方案,只是想知道哪种解决方案最好,考虑到我想使用数字ID。

我正在使用ASP.NET C#

开发我的应用程序

2 个答案:

答案 0 :(得分:4)

简而言之,您生成ID的方法注定要失败:如果您想生成唯一ID,您需要一个最终会成为瓶颈的中央服务。

还包括碎片ID闻起来很糟糕;将数据移动到新分片时会发生什么?你需要更新所有ID吗?

如果您需要可扩展的解决方案,则必须查看UUIDs或类似方法。

或者,您可以使用中央服务并为每个呼叫分配一个ID块(例如10'000)。这样,您就不需要经常使用中央服务,但如果服务失败,整个系统将会死机。

答案 1 :(得分:0)

我使用shard id(Int16)在表创建期间通过左移shard id by(64 - 16)并添加1来为每个表设置AUTO_INCREMENT值。

下一个示例是使用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; }
    }

我有很多逻辑分片最初在一台机器上。当我必须扩展时,我将不得不将整个分片移动到另一台机器并在我的查找表中更改分片ID的连接字符串。但移动后的ID生成不会受到影响。

要按ID查询分片表,我可以将分片ID设为(id >> 48),然后查询特定分片。