- 浏览: 3430441 次
- 性别:
- 来自: 珠海
文章分类
- 全部博客 (1633)
- Java (250)
- Android&HTML5 (111)
- Struts (10)
- Spring (236)
- Hibernate&MyBatis (115)
- SSH (49)
- jQuery插件收集 (55)
- Javascript (145)
- PHP (77)
- REST&WebService (18)
- BIRT (27)
- .NET (7)
- Database (105)
- 设计模式 (16)
- 自动化和测试 (19)
- Maven&Ant (43)
- 工作流 (36)
- 开源应用 (156)
- 其他 (16)
- 前台&美工 (119)
- 工作积累 (0)
- OS&Docker (83)
- Python&爬虫 (28)
- 工具软件 (157)
- 问题收集 (61)
- OFbiz (6)
- noSQL (12)
最新评论
-
HEZR曾嶸:
你好博主,这个不是很理解,能解释一下嘛//左边+1,上边+1, ...
java 两字符串相似度计算算法 -
天使建站:
写得不错,可以看这里,和这里的这篇文章一起看,有 ...
jquery 遍历对象、数组、集合 -
xue88ming:
很有用,谢谢
@PathVariable映射出现错误: Name for argument type -
jnjeC:
厉害,困扰了我很久
MyBatis排序时使用order by 动态参数时需要注意,用$而不是# -
TopLongMan:
非常好,很实用啊。。
PostgreSQL递归查询实现树状结构查询
全局唯一ID设计方案
- 博客分类:
- Database
在分布式系统中,经常需要使用全局唯一ID查找对应的数据。产生这种ID需要保证系统全局唯一,而且要高性能以及占用相对较少的空间。
全局唯一ID在数据库中一般会被设成主键,这样为了保证数据插入时索引的快速建立,还需要保持一个有序的趋势。
这样全局唯一ID就需要保证这两个需求:
全局唯一
趋势有序
全局ID产生的几种方式
数据库自增
当服务使用的数据库只有单库单表时,可以利用数据库的auto_increment来生成全局唯一递增ID.
优势:
简单,无需程序任何附加操作
保持定长的增量
在单表中能保持唯一性
劣势:
高并发下性能不佳,主键产生的性能上限是数据库服务器单机的上限。
水平扩展困难,在分布式数据库环境下,无法保证唯一性。
UUID
一般的语言中会自带UUID的实现,比如Java中UUID方式UUID.randomUUID().toString(),可以通过服务程序本地产生,ID的生成不依赖数据库的实现。
优势:
本地生成ID,不需要进行远程调用。
全局唯一不重复。
水平扩展能力非常好。
劣势:
ID有128 bits,占用的空间较大,需要存成字符串类型,索引效率极低。
生成的ID中没有带Timestamp,无法保证趋势递增
Twitter Snowflake
snowflake是twitter开源的分布式ID生成算法,其核心思想是:产生一个long型的ID,使用其中41bit作为毫秒数,10bit作为机器编号,12bit作为毫秒内序列号。这个算法单机每秒内理论上最多可以生成1000*(2^12)个,也就是大约400W的ID,完全能满足业务的需求。
根据snowflake算法的思想,我们可以根据自己的业务场景,产生自己的全局唯一ID。因为Java中long类型的长度是64bits,所以我们设计的ID需要控制在64bits。
比如我们设计的ID包含以下信息:
| 41 bits: Timestamp | 3 bits: 区域 | 10 bits: 机器编号 | 10 bits: 序列号 |
产生唯一ID的Java代码:有修改
使用自定义的这种方法需要注意的几点:
为了保持增长的趋势,要避免有些服务器的时间早,有些服务器的时间晚,需要控制好所有服务器的时间,而且要避免NTP时间服务器回拨服务器的时间。
在跨毫秒时,序列号总是归0,会使得序列号为0的ID比较多,导致生成的ID取模后不均匀,所以序列号不是每次都归0,而是归一个0到9的随机数。
使用这个CustomUUID类,最好在一个系统中能保持单例模式运行。
原文地址:http://www.androidchina.net/4744.html
全局唯一ID在数据库中一般会被设成主键,这样为了保证数据插入时索引的快速建立,还需要保持一个有序的趋势。
这样全局唯一ID就需要保证这两个需求:
全局唯一
趋势有序
全局ID产生的几种方式
数据库自增
当服务使用的数据库只有单库单表时,可以利用数据库的auto_increment来生成全局唯一递增ID.
优势:
简单,无需程序任何附加操作
保持定长的增量
在单表中能保持唯一性
劣势:
高并发下性能不佳,主键产生的性能上限是数据库服务器单机的上限。
水平扩展困难,在分布式数据库环境下,无法保证唯一性。
UUID
一般的语言中会自带UUID的实现,比如Java中UUID方式UUID.randomUUID().toString(),可以通过服务程序本地产生,ID的生成不依赖数据库的实现。
优势:
本地生成ID,不需要进行远程调用。
全局唯一不重复。
水平扩展能力非常好。
劣势:
ID有128 bits,占用的空间较大,需要存成字符串类型,索引效率极低。
生成的ID中没有带Timestamp,无法保证趋势递增
Twitter Snowflake
snowflake是twitter开源的分布式ID生成算法,其核心思想是:产生一个long型的ID,使用其中41bit作为毫秒数,10bit作为机器编号,12bit作为毫秒内序列号。这个算法单机每秒内理论上最多可以生成1000*(2^12)个,也就是大约400W的ID,完全能满足业务的需求。
根据snowflake算法的思想,我们可以根据自己的业务场景,产生自己的全局唯一ID。因为Java中long类型的长度是64bits,所以我们设计的ID需要控制在64bits。
比如我们设计的ID包含以下信息:
| 41 bits: Timestamp | 3 bits: 区域 | 10 bits: 机器编号 | 10 bits: 序列号 |
产生唯一ID的Java代码:有修改
package com.pandy.framework.core.id; import java.security.SecureRandom; /** * Created by pandy on 16-6-27. * <p/> * 项目名称: workspace * 功能说明: * snowflake是twitter开源的分布式ID生成算法,其核心思想是: * 产生一个long型的ID,使用其中41bit作为毫秒数,10bit作为机器编号,12bit作为毫秒内序列号。 * 这个算法单机每秒内理论上最多可以生成1000*(2^12)个,也就是大约400W的ID,完全能满足业务的需求。 * 根据snowflake算法的思想,我们可以根据自己的业务场景,产生自己的全局唯一ID。 * 因为Java中long类型的长度是64bits,所以我们设计的ID需要控制在64bits。 * 比如我们设计的ID包含以下信息: * | 41 bits: Timestamp | 3 bits: 区域 | 10 bits: 机器编号 | 10 bits: 序列号 | * 创建者: Pandy, * 邮箱: panyongzheng@163.com, 1453261799@qq.com * 版权: * 官网: * 创建日期: 16-6-27. * 创建时间: 下午10:59. * 修改历史: * ----------------------------------------------- */ /** * 创建的时候: workerId 可以用于标记表的序号(表少于1024个表的情况下), * 或者模块的序号(表大于1024个表的情况下,按照表属于的模块来定义这个序号), * 避免重复ID出现 * 自定义 ID 生成器 ID 生成规则: ID长达 64 bits * * | 41 bits: Timestamp (毫秒) | 3 bits: 区域(机房) | 10 bits: 机器编号 | 10 bits: 序列号 | */ public class CustomUUID { // 基准时间 private long twepoch = 1288834974657L; // Thu, 04 Nov 2010 01:42:54 GMT // 区域标志位数 private final static long regionIdBits = 3L; // 机器标识位数 private final static long workerIdBits = 10L; // 序列号识位数 private final static long sequenceBits = 10L; // 区域标志ID最大值 private final static long maxRegionId = -1L ^ (-1L << regionIdBits); // 机器ID最大值 private final static long maxWorkerId = -1L ^ (-1L << workerIdBits); // 序列号ID最大值 private final static long sequenceMask = -1L ^ (-1L << sequenceBits); // 机器ID偏左移10位 private final static long workerIdShift = sequenceBits; // 业务ID偏左移20位 private final static long regionIdShift = sequenceBits + workerIdBits; // 时间毫秒左移23位 private final static long timestampLeftShift = sequenceBits + workerIdBits + regionIdBits; private static long lastTimestamp = -1L; private long sequence = 0L; private final long workerId; private final long regionId; //workerId>=0 && workerId<1024 //regionId>=0 && regionId<8 public CustomUUID(long workerId, long regionId) { // 如果超出范围就抛出异常 if (workerId > maxWorkerId || workerId < 0) { throw new IllegalArgumentException("worker Id can't be greater than %d or less than 0"); } if (regionId > maxRegionId || regionId < 0) { throw new IllegalArgumentException( "datacenter Id can't be greater than %d or less than 0"); } this.workerId = workerId; this.regionId = regionId; System.out.println("区域标志ID最大值=" + maxRegionId + ", 机器ID最大值=" + maxWorkerId + ", 序列号ID最大值=" + sequenceMask); } public CustomUUID(long workerId) { // 如果超出范围就抛出异常 if (workerId > maxWorkerId || workerId < 0) { throw new IllegalArgumentException("worker Id can't be greater than %d or less than 0"); } this.workerId = workerId; this.regionId = 0; System.out.println("区域标志ID最大值=" + maxRegionId + ", 机器ID最大值=" + maxWorkerId + ", 序列号ID最大值=" + sequenceMask); } public long generate() { return this.nextId(false, 0); } /** * 实际产生代码的 * * @param isPadding * @param busId * @return */ private synchronized long nextId(boolean isPadding, long busId) { long timestamp = timeGen(); long paddingnum = regionId; if (isPadding) { paddingnum = busId; } if (timestamp < lastTimestamp) { try { throw new Exception("Clock moved backwards. Refusing to generate id for " + (lastTimestamp - timestamp) + " milliseconds"); } catch (Exception e) { e.printStackTrace(); } } // 如果上次生成时间和当前时间相同,在同一毫秒内 if (lastTimestamp == timestamp) { // sequence自增,因为sequence只有10bit,所以和sequenceMask相与一下,去掉高位 sequence = (sequence + 1) & sequenceMask; // 判断是否溢出,也就是每毫秒内超过1024,当为1024时,与sequenceMask相与,sequence就等于0 if (sequence == 0) { // 自旋等待到下一毫秒 timestamp = tailNextMillis(lastTimestamp); } } else { // 如果和上次生成时间不同,重置sequence,就是下一毫秒开始,sequence计数重新从0开始累加, // 为了保证尾数随机性更大一些,最后一位设置一个随机数 sequence = new SecureRandom().nextInt(10); } lastTimestamp = timestamp; return ((timestamp - twepoch) << timestampLeftShift) | (paddingnum << regionIdShift) | (workerId << workerIdShift) | sequence; } // 防止产生的时间比之前的时间还要小(由于NTP回拨等问题),保持增量的趋势. private long tailNextMillis(final long lastTimestamp) { long timestamp = this.timeGen(); while (timestamp <= lastTimestamp) { timestamp = this.timeGen(); } return timestamp; } // 获取当前的时间戳 protected long timeGen() { return System.currentTimeMillis(); } public static void main(String args[]) { CustomUUID uuid1 = new CustomUUID(1l, 0); CustomUUID uuid2 = new CustomUUID(2l, 0); for (int i = 0; i < 100; i++) { System.out.println(uuid1.nextId(false, 0)); System.out.println(uuid2.nextId(false, 0) + "-"); } } }
使用自定义的这种方法需要注意的几点:
为了保持增长的趋势,要避免有些服务器的时间早,有些服务器的时间晚,需要控制好所有服务器的时间,而且要避免NTP时间服务器回拨服务器的时间。
在跨毫秒时,序列号总是归0,会使得序列号为0的ID比较多,导致生成的ID取模后不均匀,所以序列号不是每次都归0,而是归一个0到9的随机数。
使用这个CustomUUID类,最好在一个系统中能保持单例模式运行。
原文地址:http://www.androidchina.net/4744.html
发表评论
-
MYSQL中取当前周/月/季/年的第一天与最后一天
2016-06-27 17:34 3004http://my.oschina.net/zx0211/bl ... -
按周,按月,按日,按小时分组统计数据
2016-06-27 17:07 3281http://my.oschina.net/mjRao/blo ... -
SELECT INTO 和 INSERT INTO SELECT 两种表复制语句区别
2016-06-27 16:27 1022http://my.oschina.net/MiniBu/bl ... -
CitusDB logo基于 PostgreSQL 的集群数据库 CitusDB
2016-06-20 11:43 1087http://www.oschina.net/p/citusd ... -
MYSQL级联查询,包括向上向下的级联
2016-05-31 11:47 2245http://my.oschina.net/u/178116/ ... -
阿里巴巴Druid数据源的配置与使用
2016-05-24 17:42 1550http://my.oschina.net/wjme/blog ... -
MySQL全文索引
2016-05-11 17:21 995MySQL全文索引Match Against与Like比较 h ... -
mysql中间件研究(Atlas,cobar,TDDL), 分库分表插件
2016-05-09 14:15 3456http://www.guokr.com/blog/47576 ... -
Druid使用起步—在javaWeb项目中配置监控
2016-05-06 11:41 3275Druid使用起步—在javaWeb项目中配置监控: http ... -
基于spring,Atomikos,mybatis的分布式动态数据源JTA实现
2016-04-27 16:37 1082原文;http://www.blogjava.net/zuxi ... -
用Haproxy来做PostgreSQL的负载均衡
2016-04-22 09:48 1607http://my.oschina.net/Kenyon/bl ... -
MySQL的root密码重置
2016-04-14 10:29 968http://my.oschina.net/shawnplay ... -
分布式事务管理
2016-03-31 16:43 1043http://my.oschina.net/pingpangk ... -
基于 PostgreSQL 的集群数据库 CitusDB
2016-03-25 10:24 2455http://www.oschina.net/p/citusd ... -
shell中读写mysql数据库
2016-03-13 15:32 1406http://mingxinglai.com/cn/2013/ ... -
PostgreSQL In BigData 大数据Postgresql
2016-03-10 10:00 19771.BigSQL (整合了pg和hadoop的一个开源项目) ... -
MySQL管理客户端 Adminer
2016-02-14 10:31 1557http://www.oschina.net/p/admine ... -
PostgreSQ 表的继承和分区
2016-01-08 15:02 1191PostgreSQL分区表(Table Partitionin ... -
利用系统缓存提高PostgreSQL操作效率
2015-12-17 09:01 1208http://my.oschina.net/Suregogo/ ... -
Druid 的SQL翻译功能如何使用
2015-11-27 21:40 1986Druid是阿里巴巴开源平台上的一个项目,整个项目由数据库连接 ...
相关推荐
全局唯一ID(Global Unique Identifier,简称GUID)在IT...总的来说,全局唯一ID生成是分布式系统设计中的核心问题之一,涉及多种技术和策略。理解并合理选用这些技术,对于构建高性能、高可用的分布式系统至关重要。
### 全局自增ID设计方案 #### 背景与挑战 在大型互联网应用中,随着用户数量的急剧增加,为了提升应用性能、确保系统的稳定运行,常常需要对数据库进行分库分表处理。在传统的单表环境中,数据库自带的自增ID功能...
"生成数字的全局唯一Id.zip" 提供了一个Java实现,利用雪花算法来生成Long类型的唯一ID。下面将详细解释雪花算法以及如何在Java中实现它。 雪花算法(Snowflake Algorithm)是由Twitter开源的一种分布式ID生成方案...
通过以上步骤,我们可以在SpringBoot项目中成功地集成Vesta ID Generator,为分布式系统提供稳定、高效的全局唯一ID生成方案。在高并发环境下,Vesta的优秀性能和易用性将为系统的可靠性和扩展性带来显著提升。
在分布式系统设计中,全局唯一ID的生成是数据库设计、消息队列、微服务等组件的关键部分。例如,在数据库中,主键通常需要是全局唯一的,Vesta可以提供这样的保证。在消息队列中,每条消息都需要一个唯一的ID,以便...
全局唯一ID几乎是所有设计系统时都会遇到的,全局唯一ID在存储和检索中有至关重要的作用。ID生成器在应用程序中,经常需要全局唯一的ID作为数据库主键。如何生成全局唯一ID?首先,需要确定全局唯一ID是整型还是字符...
Snowflake算法是一种基于时间戳、工作节点ID和序列号的分布式ID生成方案,确保在分布式环境中产生的ID具有全局唯一性、时间有序性和无冲突性。 然而,与Snowflake不同的是,dedid生成器的最后12位允许使用不仅仅是...
雪花ID(Snowflake ID)是一种被广泛采用的解决方案,由Twitter开源,其设计目标就是生成全局唯一的、时间序列的64位整数ID。以下我们将详细探讨这个话题。 首先,雪花ID的结构分为6部分,共64位: 1. **符号位**...
cpp-idgen是一个专门为生成全局唯一且自增ID设计的分布式高可用服务,它在C++编程语言环境下实现,适用于各种需要大量唯一标识的系统。在现代互联网应用中,尤其是在大型分布式系统中,对唯一ID的需求尤为突出,cpp-...
在分布式数据库环境中,...总的来说,解决分库分表后ID的全局唯一性问题,需要综合考虑业务需求、数据结构、算法选择以及服务架构设计等多个方面。合理选择和设计ID生成策略,对于构建高效、稳定的分布式系统至关重要。
2. UUID(通用唯一标识符):UUID是一种广泛使用的全局唯一ID生成方案,但其128位长度可能导致存储和索引效率较低。 3. 时间戳+业务流水号:结合当前时间戳和业务流水号,可以生成具有时间顺序的唯一ID,适用于对...
Sqids设计的目标是在保持ID短小的同时,确保其全局唯一性。这通常通过结合时间戳、序列号和工作节点ID来实现。时间戳确保了ID的顺序性,序列号处理同一时间戳内的并发请求,工作节点ID则区分不同的生成器,防止ID...
MySQL全局ID生成方法是数据库设计中的一个重要议题,特别是在大规模分布式系统中,确保ID的全局唯一性和高并发下的高效生成是数据库架构的关键要素。以下是一些常见的全局ID生成策略: 1. **基于CAS(Check and Set...
然而,随着数据的分散,一个新的挑战也随之而来:如何在分库分表后生成全局唯一ID(Global Unique ID,GID)。这个问题在标题“50_一个关键的问题!分库分表之后全局id咋生成?”中被明确提出。下面将详细探讨这个...
通过这种方式,可以在分布式环境下高效地生成全局唯一ID。 2. **UUID**:UUID(通用唯一标识符)是一种广泛使用的标准,它能生成128位的唯一ID。但由于UUID的生成包含随机性,可能在网络延迟或者并发较高的情况下...
分布式架构中的全局唯一序列号生成是一个关键问题,特别是在大规模并发的场景下,保证序列号的唯一性和高效生成是系统设计的重要考量。本文档主要对比分析了几种常见的解决方案,并结合携程的实践经验进行了深入探讨...
总的来说,Leaf作为一款成熟的微服务唯一ID生成方案,通过雪花算法实现了高效、可靠的全局唯一ID生成。对于开发者来说,它的易用性和高性能使得在微服务架构中集成和使用变得更加简单。结合具体的业务模块如mall-...
雪花算法广泛应用于分布式数据库、分布式消息队列、分布式锁等领域,需要全局唯一ID的地方都可以考虑使用。它的优点是简单高效,不需要中心化的协调服务,而且生成的ID具有良好的排序性,便于数据处理。 ### 7. ...
标题中的“分布式系统中唯一ID的生成方法”指的就是如何在这样一个复杂的环境中设计和实现一个有效的ID生成策略。通常,这样的系统需要处理海量的数据和高并发请求,因此ID生成器必须具备高效、可扩展以及高度可用的...