`
rensanning
  • 浏览: 3514502 次
  • 性别: Icon_minigender_1
  • 来自: 大连
博客专栏
Efef1dba-f7dd-3931-8a61-8e1c76c3e39f
使用Titanium Mo...
浏览量:37486
Bbab2146-6e1d-3c50-acd6-c8bae29e307d
Cordova 3.x入门...
浏览量:604361
C08766e7-8a33-3f9b-9155-654af05c3484
常用Java开源Libra...
浏览量:678130
77063fb3-0ee7-3bfa-9c72-2a0234ebf83e
搭建 CentOS 6 服...
浏览量:87304
E40e5e76-1f3b-398e-b6a6-dc9cfbb38156
Spring Boot 入...
浏览量:399842
Abe39461-b089-344f-99fa-cdfbddea0e18
基于Spring Secu...
浏览量:69079
66a41a70-fdf0-3dc9-aa31-19b7e8b24672
MQTT入门
浏览量:90504
社区版块
存档分类
最新评论

数据库表的ID/PK生成策略

 
阅读更多
SessionID、AccessToken、OrderID、PrimaryKey等等这些都需要一个唯一标示的ID值。

需求:
生成速度、不可推测、唯一性(高并发)、有序性

场景:
直接插入数据无需生成的ID
插入数据后需要生成的ID(主从表)

先看看Tomcat和Jetty的SessionID:

Tomcat的SessionID
https://github.com/apache/tomcat/blob/trunk/java/org/apache/catalina/util/StandardSessionIdGenerator.java

Jetty的SessionID
https://github.com/eclipse/jetty.project/blob/jetty-9.4.x/jetty-server/src/main/java/org/eclipse/jetty/server/session/DefaultSessionIdManager.java

(1)UUID/GUID
能保证唯一性,但是字节太长,无法排序,索引性能

(2)数值自动增长(auto-increment字段 / sequence)
MySQL: id bigint AUTO_INCREMENT
PostgreSQL :id bigserial

PostgreSQL :CREATE SEQUENCE users_id_seq MINVALUE 1;
nextval('users_id_seq')

插入时查找最大ID后加1:
INSERT INTO users(id, name)
VALUES ((select (case when max(id) is null then 1 else (max(id)+1) end) from users), 'xxx')


分库分表(sharding)无法保证唯一性
无法防爬虫爬数据(优惠券号码)


(3)预生成模式
使用表统一管理所有需要增长的字段,每次取出值后做加1更新:
CREATE TABLE ids (
  table_name character varying(20) NOT NULL, 
  field_name character varying(20) NOT NULL, 
  nextid bigint NOT NULL,
  CONSTRAINT ids_pkc PRIMARY KEY (table_name, field_name)
);


需要synchronized排他

(4)基于时间戳(Time-based)生成
Twitter的Snowflake

以下是Instagram采用PL/pgSQL的完整ID策略:
create sequence global_id_sequence;

CREATE OR REPLACE FUNCTION id_generator(OUT result bigint) AS $$
DECLARE
    our_epoch bigint := 1314220021721;
    seq_id bigint;
    now_millis bigint;
    -- the id of this DB shard, must be set for each
    -- schema shard you have - you could pass this as a parameter too
    shard_id int := 1;
BEGIN
    SELECT nextval('global_id_sequence') % 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 users
(
  id bigint NOT NULL DEFAULT id_generator(),
  "name" character varying(50),
  CONSTRAINT users_pkey PRIMARY KEY (id)
);
===============================================================
生成的ID:842362613529576449

最后,如何获取刚插入记录的ID的值:

MySQL:
INSERT INTO users(name) VALUES ('xxx');
SELECT LAST_INSERT_ID();


PostgreSQL:
INSERT INTO users(id, name) VALUES (1, 'xxx') RETURNING id;


JDBC 的 getGeneratedKeys() 方法:
Statement stmt = ..... ;
int count = stmt.executeUpdate( "INSERT语句", Statement.RETURN_GENERATED_KEYS);
if ( count > 0 )  {
  ResultSet rs = stmt.getGeneratedKeys();
  while( rs.next() )  {
    int generatedKey = rs.getInt( 1 ); // .....
  }
  rs.close();
}
if ( !stmt.isClosed() )  stmt.close();


参考:
https://github.com/twitter/snowflake/
https://qiita.com/kawasima/items/6b0f47a60c9cb5ffb5c4
http://instagram-engineering.tumblr.com/post/10853187575/sharding-ids-at-instagram
http://www.wekeroad.com/2014/05/29/a-better-id-generator-for-postgresql/
http://blog.codinghorror.com/primary-keys-ids-versus-guids/
http://my.oschina.net/u/142836/blog/174465
http://blog.csdn.net/bluishglc/article/details/7710738
业务系统需要什么样的ID生成器
如何在高并发分布式系统中生成全局唯一Id
分享到:
评论

相关推荐

    东北大学软件学院程序实践(四)数据库实验报告

    1)创建上面列出的还未创建的数据库表,当设定表中各列的类型和长度时,需要考虑给定的用于填充数据的INSERT语句; 2)将表TITLE4中的ISBN和Name字段设置成备用码,而且它们不能取空值; 3)在所有表中添加指定的...

    oracle数据库经典题目

    13.填写下面的语句,使其可以为Class表的ID列添加一个名为PK_CLASS_ID的主键约束。 ALTER TABLE Class Add ____________ PK_LASS_ID (Constraint) PRIMARY KEY ________ (ID) 14. 每个Oracle 10g数据库在创建后都...

    (银行卡)数据库设计报告.doc

    " "ry " " " "t_bankCard "银行卡 "管理银行卡状态 " 5.2 公告表 "表名 "t_hintInfo " "列名 "数据类型(精度范"空/非空"约束条件 "注释 " " "围) " " " " "hintId "number(10) "n "Primary "公告ID(主键名pk_...

    数据库设计规范V.docx

    长度不要超过30个字符,在PD设置生成时,部分数据库对象会自动截取到30位; 数据库设计规范V全文共10页,当前为第2页。 数据库设计规范V全文共10页,当前为第2页。 所有名称的字符范围为:A-Z, a-z, 0-9 和_(下划线)...

    数据库的设计和管理规范.doc

    " " " " " " 数据库的设计说明书 数据库设计说明书是软件产品的信息数据存储规范化的说明和指导文档,向准备从事 此数据库的生成、测试、维护人员提供专门的指导,例如数据的格式和标准,送入数据 库的操作规程和...

    图书管理系统数据库结构及实体类.doc

    "非空 " "total "Int " "非空 " "available "Int " "非空 " "intro "Text " "非空 " "logo "Varchar(32) " "非空 " "用户表 TUser " "字段名 "类型 "描述 "备注(约束) " "id "Int "主键 "主键,自增长 " "number ...

    演示怎样在Hibernate中使用复合主键

    该示例应用演示了两张表ITEM和CATEGORY_ITEM表有主外键关系,并且ITEM表的PK(ITEM_ID)是字符串,而CATEGORY_ITEM使用复合主键(CATEGORY_ID, ITEM_ID),FK是ITEM_ID字段。那么,我们这里的解决方案是使用uuid.hex...

    Hibernate注释大全收藏

    这种策略支持双向的一对多关联,但不支持 IDENTIFY 生成器策略,因为ID必须在多个表间共享。一旦使用就不能使用AUTO和IDENTIFY生成器。 每个类层次结构一张表 @Entity @Inheritance(strategy=InheritanceType....

    sql语句生成标准的字典

    自动生成数据字典。 SELECT 表名=case when a.colorder=1 then d.name else '' end, --字段序号=a.colorder, 字段名=a.name, 字段说明=isnull(g.[value],''), --标识=case when COLUMNPROPERTY( a.id,a.name,'...

    jfinalQ-gencode:jfinalQ对应的代码生成工具

    jfinalQ-gencodejfinalQ代码生成工具采用velocity模版技术可以多表同时生成基于,易学,开发快速,功能强大基于,简洁美观,完美适配移动端:jfinalQ最简化示例:jfinalQ自带代码生成工具:jfinalQ自带tomcat加密...

    Bootstrap_FileUpload4.3.9+Drapper+IOC+MVC

    数据库表: CREATE TABLE [dbo].[CCPC_ECG_IMAGES]( [ID] [varchar](36) NOT NULL, [REGISTER_ID] [varchar](36) NOT NULL, [FILE_NAME] [varchar](200) NOT NULL, [TYPE] [int] NOT NULL, [UPLOAD_TIME] ...

    超级简单SQL查询构建器-Golang开发

    goql goql是一种超级快速且易于使用的查询生成器和数据库表来构造建模约定。 它就像一个ORM,但是它不碍您,让您可以控制查询。 对于以下示例,goql goql是一种超级快速且易于使用的查询生成器和数据库表,以构建...

    软件工程工资管理系统

    13 ID 自动 4 员工信息 员工信息表ID 14 编号 文本 50 员工信息 员工编号 15 科室 文本 255 员工信息 员工所在科室 16 姓名 文本 255 员工信息 员工姓名 17 生日 文本 50 员工信息 员工生日 18 政治面貌 文本 ...

    PDMan-win64_v2.1.2.exe使用说明

    我的示例模板 =========模板开始================== ... $blankline import javax.persistence.*; import java.io.Serializable; import java.util.Date;...import lombok.Data;...数据库新加的表需要重新导入

    scaffenger:Laravel 5.1 脚手架生成器

    总共支持 17 种列类型,包括: 列类型描述pk 表的主键(通常是id ) slug 被名称为title和 type text的列slugified的varchar text 纯文本textarea 纯文本区域password 密码列(具有更改或不预加载其值等的多种功能...

    oracle学习文档 笔记 全面 深刻 详细 通俗易懂 doc word格式 清晰 连接字符串

    ORACLE数据库系统是美国ORACLE公司(甲骨文)提供的以分布式数据库为核心的一组软件产品,是目前最流行的客户/服务器(CLIENT/SERVER)或B/S体系结构的数据库之一。  拉里•埃里森  就业前景 从就业与择业的...

    暴雨:从强大的“暴风雨”库中获得的BoltDB工具包,以及性能改进

    实际上,在风暴中,PK索引(也称为ID)是唯一的索引。 从本质上讲,ID已经是唯一的,因此无需索引该ID。 这样,暴雨使用主键作为ID,因此几乎所有通过ID索引进行的操作都将尽快执行。 暴风雨是从3.1.0版本的风暴库...

    odata-editor:OData简单查看和编辑JavaScript库(WIP)

    数据编辑器 简单查看和编辑javascript库(WIP)。 简而言之, 允许针对服务器“模式”的REST操作。 odata-editor使您的后台办公和管理表数据输入像... 为生成的html提供一个html容器ID var uischema = { Person :

    sql2005全文检索.doc

     在 SQL Server 2005 中,SQL 协议处理程序的工作是从指定数据库中的表内访问数据。  断字符  断字符是用于在查询或抓取的文档中确定字符流中的字符边界位置。有关详细信息。  全文搜索的索引组件负责全文索引的...

Global site tag (gtag.js) - Google Analytics