`
fujohnwang
  • 浏览: 156280 次
社区版块
存档分类
最新评论

Why We Need A Global ID Generator?!

    博客分类:
  • Tech
阅读更多

Table of Contents

1. Pains In The Neck

我们先得从MySQL的自增长主键说起...

1.1. MySQL的自增长主键的问题(The Problem With MySQL's Auto-Increment ID)

考虑到系统的可用性以及地理区域内的访问效率等特点, 我们需要在两个处于不同地理区域的机房中的MySQL之间进行数据的同步, 为了避免位于不同机房中的MySQL在进行同步的时候出现数据冲突, 通常会为它们指派不同的主键范围(当然采用的是MySQL默认的自增主键支持), 例如:

DB Node A: 0-99999 
DB Node B: 100000- 199999
				

如果我们只是将Node A的数据单向同步到另一个机房的Node B中, 那么So far so good, 整个过程将按照我们所预想的那样进行.可是, 一旦我们要将Node B的数据单向或者双向的同步到Node A, 那么问题就来了.

问题在于, 如果将自增主键范围较大的主键同步到自增主键范围较小的数据库, 那么, 自增主键范围较小的数据库的自增序列的默认行为将被打破, 即新生成的自增主键将从最大的主键开始. 以Node A和Node B来讲就是, 如果我将100001的数据同步到Node A, 那么, Node A后面生成的自增主键将以100001为基础施行自增长, 这完全打破了最初为它指定的自增长范围, 既然最初的数据同步的前提条件被打破, 那么后继的所有行为和结果就都乱套了.

也就是说, 如果不需要类似以上的数据同步, 或者只是将范围较小的自增主键对应的数据同步到范围较大的数据库,那自增主键的使用是没有太大问题的. 可是一旦出现双向同步或者单向的将较大的自增主键数据同步到较小的自增主键数据库中,那么, MySQL的自增主键策略就会带来问题了.

1.2. Similar Problem With Credit's Scenario On DB2

依稀记得阿九提到过Credit项目组在进行数据导入的时候也会存在类似头疼的问题, 从一个库导入数据到另一个库的时候, 都需要修改外键引用的值才可以, 这也是因为使用了MySQL的自增主键类似的策略导致的. 更多细节可以参考阿九的blog: http://trydofor.iteye.com/blog/668705

这两个场景不是说自增主键不好, 而是说在某些场景下, 自增主键会变成一间令人头疼的事情, 比如上面提到的数据同步之类的场景.

2. What We Do?

既然在以上场景中数据库自带的自增主键策略无法满足需要, 那我们当然就得另寻他路咯. 我们采用客户端生成主键的策略, 但UUID/GUID不在考虑之列, 主要因为是UUID/GUID对索引, 范围查询等很不友好, 当然生成速度和存储空间也包含在排除因素之列.

从各个方面来讲, 数字增长型主键依然是我们倾向于使用的主键策略. 当然, 其它类型的主键在某些场景下也可以考虑(比如, 对索引来说比UUID/GUID要友好一些的符合某种格式的字符串类型的主键). 为了实现这样的一个主键生成服务, 我们可以选择两条路...

2.1. 打造我们自己的主键生成器(Roll Our Own ID Generator)

实际上, 搞这么一个东西并没有太大的难度, 所以, 展开来细说也没有太多的必要,我们这里只提几个实现这样一个自定义的主键生成器的时候需要考虑的点.

第一个就是行为的抽象. 最简单的抽象可能可能是:

public interface IDGenerator{
	Long nextKey();
}
				

我们可以根据自己场景的需要引入更多的抽象行为.

第二个需要考虑的就是状态的存储方式, 是存储到内存, 还是文件,亦或数据库当中, 这个要根据这些存储媒介的特性以及其它因素来进行权衡. 比如内存状态易失, 那么, 就意味着基于内存的主键状态存储只能限定于指定生命周期范围内的应用场景. 对文件或者数据库等存储方式来说, 也需要类似的考虑.

第三个需要考虑的就是主键生成器部署场景, 是嵌入到应用程序内, 还是以独立的服务进行部署. 不管采用那种部署方式, 我们需要进一步考虑在这些部署场景下主键生成器的轻量性, 灵活性以及可用性. 至于如何来满足这些特性需求, 那就是“八仙过海, 各显神通 ”了. 比如为了保证可用性, 我们可以进行运行期间的failover; 为了让其更轻量,更灵活, 我们可以对状态的管理方式进行权衡, 选用最合适的方案等等.

其它点可能就是实现期间的一些事情了, 比如增长的步长, 本地缓存以提高生成效率, 主键的分区等等.

2.2. 利用甚至扩展现有的 Spring的 DataFieldMaxValueIncrementor(Extends Spring's DataFieldMaxValueIncrementor Abstraction)

实际上, Spring框架已经有一个现成的抽象,即DataFieldMaxValueIncrementor, 它基本上可以满足这种自定义主键生成器的场景, 从该接口的定义也可以看出来:

public interface DataFieldMaxValueIncrementer {
	int nextIntValue() throws DataAccessException;
	long nextLongValue() throws DataAccessException;
	String nextStringValue() throws DataAccessException;
}
				

基本上该抽象已经可以满足需要, 而且, Spring框架自身也提供了许多针对不同数据库的实现, 大家可以从Spring相关文档和书籍中获取更多详细信息.(当然, 拙作<<Spring>>中也或多或少提到他.)

当然, 默认的一些实现可能无法满足所有应用的需要, 那么,我们就可以在这些现有工作的基础上进行扩展, 加入一些其它逻辑以支持自身场景的需要,比如加入HA之类考虑.

3. 结束语 (Conclusion)

其实这个话题真得很没说头, 呵呵, 都过去了这么些年了, 想把这个写出来完全是因为眼前看到相关team遇到的一些问题, 以及联想到之前的一些零星思绪片段, 所以就简单整理一下, 摆出来权作抛砖引用吧!

BTW. 好像记得flickr的一个工程师写过类似的东西, 介绍flickr如何实现这样的东西, 链接找不到了, 大体上是使用MySQL的MyISAM做存储, 然后两个库采用不同的主键步长来保证HA, 不过, 记得当时看过之后感觉不靠谱,大家感兴趣可以搜一下看看.

分享到:
评论
1 楼 trydofor 2010-05-18  
uuid/guid  128bit 有点太长了,牛刀杀鸡。
现在有个想法,是用 long/bigint 64bit
用前几个byte或bit进行主机标识,后面作为序号。
# 0xFFF0000000000000 instance 4096
# 0x000FFFFFFFFFFFFF sequence 4503599627370496

相关推荐

    还在使用MyBatis Generator?试试这个工具.docx

    通过在 Maven 或 Gradle 构建系统中配置 `mybatis-generator-maven-plugin` 或 `mybatis-generator-plugin`,开发者可以指定配置文件 `mybatis-generator-config.xml` 来定义生成规则。配置文件中包含了数据库连接...

    A Simple Mesh Generator in MATLAB

    A Simple Mesh Generator in MATLABA Simple Mesh Generator in MATLABA Simple Mesh Generator in MATLABA Simple Mesh Generator in MATLAB

    js代码-Generator!!!

    在JavaScript的世界里,Generator是一种非常重要的特性,它允许我们创建迭代器,并且可以暂停和恢复执行流程,这对于处理异步操作或生成大量数据时非常有用。Generator是ES6(ECMAScript 2015)引入的新特性,极大地...

    A SIMPLE MESH GENERATOR IN MATLAB

    We want to offer a short and simple MATLAB code, described in more detail than usual, so the reader can experiment (and add to the code) knowing the underlying principles. We find the node locations ...

    idgenerator:idgenerator是基于redis的id生成器

    idgenerator是基于redis的id生成器 dgenerator是基于redis的id生成器 安装 取得 go get github.com/lbfatcgf/idgenerator 快速开始 package main import ( "fmt" "net/http" "os" "os/signal" "syscall" ...

    asy_generator.rar_ INDUCTION GENERATOR_asy_generator_induction_发

    标题中的“asy_generator.rar_ INDUCTION GENERATOR_asy_generator_induction_发”指的是一个关于异步发电机(Asynchronous Generator)的MATLAB模型文件。这个压缩包可能包含了一个用于模拟和分析异步发电机工作...

    一个简单的自定义ID 生成器IDGenerator

    一个用Java 编写简单的自定义ID 生成器IDGenerator

    图像描述--Show and Tell: A Neural Image Caption Generator

    完整工程案例:图像描述---Show and Tell: A Neural Image Caption Generator,基于Inception V3与LSTM实现图像描述,运行环境(Tensorflow1.0及以上,Python3.6)

    idgenerator分布式主键ID生成器

    迄今为止最全面的分布式主键ID生成器。优化的雪花算法(SnowFlake)——雪花漂移算法,在缩短ID长度的同时,具备极高瞬时并发处理能力(50W/0.1s)。 原生支持 C#/Java/Go/Rust/C/SQL 等多语言,且提供 PHP 扩展及 ...

    Hibernate的generator属性

    这个属性可以配置在 `hibernate.hbm.xml` 文件中的 `&lt;id&gt;` 标签内,它允许你选择不同的策略来生成 ID。 1. **identity**:这个生成器适用于像 MySQL 这样的数据库,它依赖于数据库自身的自动递增功能。例如,在 ...

    asy_generator_load.rar_asy_generator_induction motor_发电机 matlab_

    在MATLAB环境中,异步发电机(ASY Generator)的模型与应用是电力系统研究的重要部分,尤其是在模拟和分析电力系统的动态行为时。这个“asy_generator_load.rar”压缩包包含了一个名为“asy_generator_load.mdl”的...

    迄今为止最全面的分布式主键ID生成器,多语言新雪花算法(SnowFlake IdGenerator).zip

    迄今为止最全面的分布式主键ID生成器。 优化的雪花算法(SnowFlake)——雪花漂移算法,在缩短ID长度的同时,具备极高瞬时并发处理能力(50W/0.1s)。 原生支持 C#/Java/Go/Rust/C/SQL 等多语言,且提供 PHP 扩展及 ...

    DistMesh - A Simple Mesh Generator in MATLAB (有限元等网格剖分)

    DistMesh, A Simple Mesh Generator in MATLAB, 有限元网格剖分不错工具,可做项目测试用,二维三维都可剖分,其主页介绍:http://persson.berkeley.edu/distmesh/

    mybatis_generator使用手册

    MyBatis Generator 使用手册 MyBatis Generator 是 MyBatis 的代码生成工具,旨在通过反射数据库表结构生成对应的Java代码,简化开发过程,提高开发效率。本手册将指导用户如何使用 MyBatis Generator 生成代码,...

    hibernate中的generator的生成方式hibernate中的generator的生成方式

    在Hibernate中,`Generator`是负责生成主键值的策略,通常在`&lt;id&gt;`元素中通过`class`属性指定。不同的数据库和不同的应用场景可能需要不同的生成策略。接下来,我们将逐一介绍各种常见的生成策略及其适用场景。 ###...

    idGenerator

    "IdGenerator"是一个在JavaScript环境中用于生成唯一标识符(ID)的工具或库。在Web开发中,尤其是在处理大量动态数据或需要跟踪和管理多个对象时,生成唯一ID至关重要。JavaScript作为前端的主要编程语言,其内建...

    Msc-generator使用手册

    Msc-generator是一款用于从文本描述中绘制各种图表的工具,它的版本为6.1.0,更新于2017年11月3日。这款工具可以生成多种类型的图表,包括信号图、流程图、块图等,每种图表都有其特定的用途和特点。为了更好地理解...

    id-generator:生成带有前缀的随机ID(la Stripe)

    var IdGenerator = require ( 'auth0-id-generator' ) ; var generator = new IdGenerator ( ) ; var id = generator . new ( 'cus' ) ; console . log ( id ) ; // cus_lO1DEQWBbQAACfHO 预定义的一组允许的前缀...

    百度分布式id 代码uid-generator

    说的简单一点就是:应用在启动时会往数据库表(uid-generator需要新增一个WORKER_NODE表)中去插入一条数据,数据插入成功后返回的该数据对应的自增唯一id就是该机器的workId,而数据由host,port组成。

Global site tag (gtag.js) - Google Analytics