前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >生成全局ID

生成全局ID

作者头像
用户1148526
发布2019-05-25 19:46:11
8840
发布2019-05-25 19:46:11
举报
文章被收录于专栏:Hadoop数据仓库Hadoop数据仓库

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://cloud.tencent.com/developer/article/1433220

代码语言:txt
复制
    对[**数据库**](http://lib.csdn.net/base/mysql)表进行水平分割的时候,经常会遇到在不同的机器上生成全局唯一ID的问题。下面以[**MySQL**](http://lib.csdn.net/base/mysql)为例介绍对于在不同机器上生成全局唯一ID的几个解决途径,其思想也适用于其他数据库系统。

1. 使用auto_increment_increment和auto_increment_offset

代码语言:txt
复制
    假定有n个数据库,它们使用了auto\_increment字段来取得唯一ID,为了保证n个数据库同时具备全局唯一性,我们可以在每个数据库上分别指定初始值和步长,具体如下:

对于任一节点i(1<=i<=n)指定

auto_increment_increment=i

auto_increment_offset=n

如果以后系统扩展到m个数据库(m>n),则:

对于任一节点i(1<=i<=m)指定

auto_increment_increment=全局max(id)+i

auto_increment_offset=m

这种方法很简单,而且也不依赖于一个中心节点,因此是生成唯一ID的上佳选择。现有的服务器也很容易用这个方法来配置,特别是当你增加服务器或灾难恢复之后。

2. 在全局节点上创建一个表

代码语言:txt
复制
    在一个全局数据库节点上创建一个带有auto\_increment字段的表,应用就从这个表取得唯一性ID。

sql view plain copy

  1. -- 建立myisam全局表
  2. create table single_row
  3. (
  4. col1 int not null auto_increment,
  5. col2 int not null
  6. primary key(col1),
  7. unique key(col2)
  8. ) engine=myisam;
  9. -- 用replace让表里的数据保持一条
  10. replace into single_row (col2) values (1);
代码语言:txt
复制
    在这个语句执行后,可以使用MySQL的API:mysql\_insert\_id()来获得这个新生成的值。这个方法在不同语言中的实现都不太一样,以下是一个PERL的例子:

python view plain copy

  1. my $sth = $dbh -> prepare('replace into single_row(col2) values (1)');
  2. while (my $item = @work_to_do){
  3. $sth->execute();
  4. my $id = $dbh->(mysql_insert_id);
  5. #Do the work...
  6. }
代码语言:txt
复制
    用不着再使用另外的查询语句(比如select last\_insert\_id())来获取这个值。额外的查询又会在服务器之间多一次往返,这很没效率。如果使用这种全局分配器来产生唯一ID,要当心它会成为应用的瓶颈。

3. 使用memcache

代码语言:txt
复制
    在memcache API中有个incr()函数,它能产生一个唯一性ID供使用。虽然memcache很快(每秒钟几万个值),但它不是持续不断的。每次重启了memcache服务,都需要在缓存里初始化那个产生值。这就要求你初始化时,每次都要找出目前在各个数据分块使用的最大值,这个过程相当缓慢而且难以自动执行。

4. 批量分配编号

代码语言:txt
复制
    应用从全局节点上一次性地取得一批编号供自己使用,用完后,再申请一批。

5. 使用复合值

代码语言:txt
复制
    你可以使用一个复合值来做唯一性ID,比如一个数据库ID和自增长编号。可以使用单列主键值,并且使用整数的“高位”来保存数据库ID。简单的左移位(乘法)和加法可以完成这一目的。例如,使用无符号的bigint(64位)的高8位来保存数据库ID,那么就可以用下面的方式在数据库15上插入11:

insert into test(pk_col,...) values ((15<<56)+11,...);

这种方法的问题是需要额外的方式来产生键值,因为auto_increment不会帮助你做这件事。而且这种方法使主键值更大了,对InnoDB中的次主键有多重影响。

6. 使用双字段auto_increment键

代码语言:txt
复制
    这个只能在myisam表里使用:

sql view plain copy

  1. create table inc_test
  2. (
  3. a int nout null,
  4. b int not null auto_increment,
  5. primary key (a,b)
  6. ) engine=myisam;
  7. insert into inc_test(a) values(1),(1),(2),(2);
  8. select * from inc_test;

7. 使用GUID

代码语言:txt
复制
    你可以使用UUID()函数来生成全局唯一的ID,GUID的值很大且不连续,因此它不适合做InnoDB表里的主键。MySQL中新的UUID\_SHORT函数能返回一个较短的连续的值,也更适于用作主键。
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016年12月28日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档