雪花算法(01)介绍

针对每个公司,随着服务化演进,单个服务越来越多,数据库分的越来越细,有的时候一个业务需要分成好几个库,这时候自增主键或者序列之类的主键id生成方式已经不再满足需求,分布式系统中需要的是一个全局唯一的id生成规则。既然号称在全局分布式系统中唯一,那么主键的生成规则必然要复杂一些,以前看过很多资料,都对雪花的生成一知半解,最后才发现是对Java的位运算没有彻底了解,这里想针对雪花算法,以一种浅显的的方式来进行学习,去除以前的一知半解和对雪花算法的神秘感。



 

雪花算法生成的最终结果其实就是一个long类型的Java长整型数字,这是一个大前提!算法所有的内容都是针对这个数字进行运算的。Java基础类型相信都很熟悉,有32位的整型int类型,和64位的长整型long类型。我们单说long类型,64位说的是数字转换为二进制形式时候的表现,其中第一位表示的是正负,也就是符号,剩下的63位表示的是字面数字。我们来简单看一下几个关键的long数字转换成二进制的形式:

再来看一个二进制数字转换为long类型:

上面都是Java基础知识,相信大家都懂。


 

生成一个long类型的数字id,其实就是对这64位的二进制形式里面填值,把这64位分成几个部分,彼此间互不影响,每部分都有自己的生成规则,这样在一定的简单的大前提下,能保证全局唯一。

先说第一位,long类型的数字是有符号的,第一位是0就是正数,1是负数,我们生成的id必然要正数,所以第一位可以确定为0不变。

剩下的63位分成三大部分,第一部分占41位,用来表示时间,什么时间后面会详细介绍。第二部分占10位,用来表示程序所在机器的信息,剩下的第三部分占12位,填充的是一个序列,可以理解为递增数字,这样前面的时间和机器数字如果都一样的话,用序列的区别来生成不同的id。

上面的三大块信息转换成数字,填充到63位当中,基本可以保证任何时间任何机器生产的任何id不重复,可以推理出,时间和序列都是不可控的,但是机器信息是我们可以控制的,也就是说设置好机器信息是分布式id不重复的关键。

根据上面的理论可以开始学习雪花算法。


 

代码地址:https://gitee.com/blueses/snowflake-demo 01

Java雪花算法是一种用于生成唯一ID的算法,它可以在分布式系统中生成全局唯一的ID。下面是Java雪花算法生成ID的介绍: 1. 雪花算法的原理: 雪花算法使用一个64位的整数来表示生成的ID,其中包含了以下几个部分: - 时间戳:占用41位,精确到毫秒级别,可以支持约69年的时间戳。 - 机器ID:占用10位,用于标识不同的机器,可以支持最多1024台机器。 - 序列号:占用12位,用于标识同一毫秒内生成的不同ID,可以支持每台机器每毫秒生成最多4096个ID。 2. Java实现雪花算法生成ID的步骤: - 定义一个起始时间戳,作为基准时间。 - 获取当前时间戳,并与基准时间进行比较,计算出时间差。 - 根据时间差、机器ID和序列号生成一个64位的ID。 3. Java代码示例: ```java public class SnowflakeIdGenerator { private static final long START_TIMESTAMP = 1609459200000L; // 2021-01-01 00:00:00 private static final long MACHINE_ID_BITS = 10L; private static final long SEQUENCE_BITS = 12L; private static final long MAX_MACHINE_ID = ~(-1L << MACHINE_ID_BITS); private static final long MAX_SEQUENCE = ~(-1L << SEQUENCE_BITS); private static final long MACHINE_ID_SHIFT = SEQUENCE_BITS; private static final long TIMESTAMP_SHIFT = MACHINE_ID_BITS + SEQUENCE_BITS; private static final long MACHINE_ID = getMachineId(); // 获取机器ID private static long lastTimestamp = 0L; private static long sequence = 0L; public synchronized static long generateId() { long currentTimestamp = System.currentTimeMillis(); if (currentTimestamp < lastTimestamp) { throw new RuntimeException("Clock moved backwards. Refusing to generate id."); } if (currentTimestamp == lastTimestamp) { sequence = (sequence + 1) & MAX_SEQUENCE; if (sequence == 0) { currentTimestamp = waitNextMillis(currentTimestamp); } } else { sequence = 0L; } lastTimestamp = currentTimestamp; return ((currentTimestamp - START_TIMESTAMP) << TIMESTAMP_SHIFT) | (MACHINE_ID << MACHINE_ID_SHIFT) | sequence; } private static long waitNextMillis(long currentTimestamp) { while (currentTimestamp <= lastTimestamp) { currentTimestamp = System.currentTimeMillis(); } return currentTimestamp; } private static long getMachineId() { // 根据实际情况获取机器ID,可以使用IP地址、MAC地址等方式 // 这里简化为固定的一个值 return 1L; } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值