文档章节

MySQL分库分表环境下全局ID生成方案

豌豆
 豌豆
发布于 2013/11/06 01:16
字数 810
阅读 21068
收藏 335

在大型互联网应用中,随着用户数的增加,为了提高应用的性能,我们经常需要对数据库进行分库分表操作。在单表时代,我们可以完全依赖于数据库的自增ID来唯一标识一个用户或数据对象。但是当我们对数据库进行了分库分表后,就不能依赖于每个表的自增ID来全局唯一标识这些数据了。因此,我们需要提供一个全局唯一的ID号生成策略来支持分库分表的环境。下面来介绍两种非常优秀的解决方案:

###1. 数据库自增ID——来自Flicker的解决方案

因为MySQL本身支持auto_increment操作,很自然地,我们会想到借助这个特性来实现这个功能。Flicker在解决全局ID生成方案里就采用了MySQL自增长ID的机制(auto_increment + replace into + MyISAM)。一个生成64位ID方案具体就是这样的:
先创建单独的数据库(eg:ticket),然后创建一个表:

CREATE TABLE Tickets64 (
            id bigint(20) unsigned NOT NULL auto_increment,
            stub char(1) NOT NULL default '',
            PRIMARY KEY  (id),
            UNIQUE KEY stub (stub)
    ) ENGINE=MyISAM

当我们插入记录后,执行SELECT * from Tickets64,查询结果就是这样的:

+-------------------+------+
| id                | stub |
+-------------------+------+
| 72157623227190423 |    a |
+-------------------+------+

在我们的应用端需要做下面这两个操作,在一个事务会话里提交:

REPLACE INTO Tickets64 (stub) VALUES ('a');
SELECT LAST_INSERT_ID();

这样我们就能拿到不断增长且不重复的ID了。
到上面为止,我们只是在单台数据库上生成ID,从高可用角度考虑,接下来就要解决单点故障问题:Flicker启用了两台数据库服务器来生成ID,通过区分auto_increment的起始值和步长来生成奇偶数的ID。

TicketServer1:
auto-increment-increment = 2
auto-increment-offset = 1

TicketServer2:
auto-increment-increment = 2
auto-increment-offset = 2

最后,在客户端只需要通过轮询方式取ID就可以了。

  • 优点:充分借助数据库的自增ID机制,提供高可靠性,生成的ID有序。
  • 缺点:占用两个独立的MySQL实例,有些浪费资源,成本较高。

参考:http://code.flickr.net/2010/02/08/ticket-servers-distributed-unique-primary-keys-on-the-cheap/

###2. 独立的应用程序——来自Twitter的解决方案

Twitter在把存储系统从MySQL迁移到Cassandra的过程中由于Cassandra没有顺序ID生成机制,于是自己开发了一套全局唯一ID生成服务:Snowflake。GitHub地址:https://github.com/twitter/snowflake。根据twitter的业务需求,snowflake系统生成64位的ID。由3部分组成:

41位的时间序列(精确到毫秒,41位的长度可以使用69年)
10位的机器标识(10位的长度最多支持部署1024个节点)
12位的计数顺序号(12位的计数顺序号支持每个节点每毫秒产生4096个ID序号)

最高位是符号位,始终为0。

  • 优点:高性能,低延迟;独立的应用;按时间有序。
  • 缺点:需要独立的开发和部署。

推荐阅读:MySQL使用优化与总结

© 著作权归作者所有

豌豆
粉丝 48
博文 8
码字总数 14300
作品 0
海淀
程序员
私信 提问
加载中

评论(32)

linuxfs
linuxfs

引用来自“王海平”的评论

第一种方案在高并发的情况下会出现相同id冲突的问题,而且每个提交的程序都需要耦合自增字段的事务提交,不是什么多优秀的方案?第二种没详细介绍,感觉对小网站没什么参考价值,而且64位这个不明白为什么非要这个?我们现在的方案是直接使用redis的自增字段,独立部署,每次获取一个+1后的值,非常简单非常稳定,更容易维护。

引用来自“pxllong”的评论

所以他用mysql的myisam myisam不支持事务
可以参考一下replace into语句的来源,它出现的时候还没有innodb表而且还没有支持事务,所以replace into本身就已经能保证是原子性的了。
p
pxllong

引用来自“王海平”的评论

第一种方案在高并发的情况下会出现相同id冲突的问题,而且每个提交的程序都需要耦合自增字段的事务提交,不是什么多优秀的方案?第二种没详细介绍,感觉对小网站没什么参考价值,而且64位这个不明白为什么非要这个?我们现在的方案是直接使用redis的自增字段,独立部署,每次获取一个+1后的值,非常简单非常稳定,更容易维护。
所以他用mysql的myisam myisam不支持事务
胡建鸿
胡建鸿
其实分裤库可以参照mongodb的objectID生成策略,保证不同数据库服务器生成唯一字段
dhljs
dhljs
问一下, 这两种方案能保证 第一次请求的id一定比第二次请求的id小吗?
haanya168
haanya168
看不明白,楼主应该给出一条记录插入那个库的方案。
王海平
王海平
第一种方案在高并发的情况下会出现相同id冲突的问题,而且每个提交的程序都需要耦合自增字段的事务提交,不是什么多优秀的方案?第二种没详细介绍,感觉对小网站没什么参考价值,而且64位这个不明白为什么非要这个?我们现在的方案是直接使用redis的自增字段,独立部署,每次获取一个+1后的值,非常简单非常稳定,更容易维护。
酒逍遥
酒逍遥
关键是 有序 和 不重复 ....
豌豆
豌豆 博主

引用来自“萌龙”的评论

引用来自“滔哥”的评论

看来太菜, 生成64位ID方案 看不太明白了

这个跟mongodb的_id很像,这个的好处是支持了时间顺序的同时,还支持多节点

是的。
netkiller-
netkiller-
难度不再与ID怎么生成,而是索引。
豌豆
豌豆 博主

引用来自“华佗”的评论

REPLACE INTO Tickets64 (stub) VALUES ('a');
实际上是删除,再插入,这样效率有问题呀!

效率不会差多少。可以考虑用多个mysql实例做负载均衡(在客户端做)。
大型互联网应用去Oracle改造经验总结——全局id生成服务设计和实现

ID的特性 id是唯一标识一条数据的,它一般没有什么业务含义,是系统内部的标识,那么它往往有这样一些特性。 全局唯一性。这个是强制的,往往id会被设置成主键,肯定不允许重复。 顺序性。这...

杨武兵
2016/04/01
219
0
数据库分库分表(sharding)系列(二) 全局主键生成策略

本文将主要介绍一些常见的全局主键生成策略,然后重点介绍flickr使用的一种非常优秀的全局主键生成方案。关于分库分表(sharding)的拆分策略和实施细则,请参考该系列的前一篇文章:数据库分库...

bluishglc
2012/07/03
0
0
mycat全局系列号的学习和配置

为什么需要全局系列号: 产品介绍: 在实现分库分表的情况下,数据库自增主键无法保证自增主键的全局唯一。为此,mycat提供了全局sequence,并且提供了包含本地配置和数据库配置多种实现方式...

am2012
2017/12/28
0
0
每秒处理10万订单支付架构

一、库分表 在redis,memcached等缓存系统盛行的互联网时代,构建一个支撑每秒十万只读的系统并不复杂,无非是通过一致性哈希扩展缓存节点,水平扩展web服务器等。支付系统要处理每秒十万笔订...

rickiyeat
2017/11/09
0
0
【分布式架构之旅-理论篇】数据库分库分表

前言 储备知识ing,很久之前写的。 MySQL集群 MySQL官方提供的是mysql-proxy方案,主要解决了高并发的问题,但是没有解决高可用的问题。一般项目都是读多写少。读的操作让mysql-slave去处理,...

cmazxiaoma
2017/12/18
0
0

没有更多内容

加载失败,请刷新页面

加载更多

GMTC2019|闲鱼-基于Flutter的架构演进与创新

作者:闲鱼技术-宗心 2012年应届毕业加入阿里巴巴,主导了闲鱼基于Flutter的新混合架构,同时推进了Flutter在闲鱼各业务线的落地。未来将持续关注终端技术的演变及趋势 Flutter的优势与挑战 ...

阿里云云栖社区
15分钟前
2
0
迪蒙人工智能共享停车吸引国际关注

  近来,华为创始人任正非多次提及人工智能。即便在华为生死攸关的关键时刻,任正非依旧不忘强调教育的重要性,“如果不重视教育,实际上我们会重返贫穷的,因为这个社会,最终是要走向人工智能的...

琴殇的
16分钟前
0
0
iOS开发之EventKitUI框架的应用

iOS开发之EventKitUI框架的应用 前面博客,有介绍EventKit这个框架的使用,使用EventKit可以与系统的日历和提醒应用进行交互,读写用户的日程事件。EventKitUI,顾名思义,其实基于EventKit框...

珲少
24分钟前
0
0
从MySQL源码看其网络IO模型

从MySQL源码看其网络IO模型 前言 MySQL是当今最流行的开源数据库,阅读其源码是一件大有裨益的事情(虽然其代码感觉比较凌乱)。而笔者阅读一个Server源码的习惯就是先从其网络IO模型看起。于是...

无毁的湖光-Al
25分钟前
0
0
WebService学习笔记

什么是Web Services? Web Services 是应用程序组件 Web Services 使用开放协议进行通信 Web Services 是独立的(self-contained)并可自我描述 Web Services 可通过使用UDDI来发现 Web Serv...

榴莲黑芝麻糊
41分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部