Mybatis中的雪花算法(如何生成的?可以逆推出ip嘛?)

引言

我们在进行数据存储时,往往会因为数据量过大导致一个表不足以放下所有数据。这时我们就会进行分库分表,而如果我们使用水平分表的话,就会遇到一个问题:ID如何保证唯一?

1.我们可以使用ID的起始位置不同,通过步长等于表数,做到ID唯一,但终究是局限的,万一还要增加表呢?

2.我们可以使用UUID做唯一ID,但我们一般使用id都是有序的,这样明显用着不舒服。

所以在这样的场景下产生了新的算法:

  • "雪花算法":ID生成策略,按照时间顺序生成分布式唯一ID。

正文

  • 在项目的application文件中有这样的配置来生成id。

  • 这里也可以自己设置work-id,datacenter-id,但记得需要同时赋值(具体可以看源码中的生成过程)

  • 深入源码中,我们发现,原来ID是按照这样的结构来实现的:

  • 可以看到,这边源码显示,是使用了|运算,将我们所需的四个部分拼接在一起。

  • 时间戳往左偏移22位,留了22位给节点编号和序列号,节点编号中有datacenterId+workerId,序列号占用12位。那么节点编号中的两个值各占5位。

  • 41+10+12+1 = 64,刚好为64,那么这就是雪花算法。

具体值含义:

  • 符号位:固定为0

  • 时间戳:占用41位,是从固定时间点到当前时间的毫秒数,转换成二进制后是ID的第2~42位

  • 节点编号:占用10位,表示不同节点,对于同一个程序来说,可以固定写死一个节点编号,转换成二进制后是ID的第43~52位

  • 序列号:占用12位,表示同一节点在同一毫秒内的不同序列号,每个序列号都会自增,最大值是4095,转换成二进制后是ID的第53~64位。

  • 可以看到这两个值都是系统按照ip生成的,所以可以代表某个集群ip的唯一标识。

检验过程

  • 我们可以拿目前的ID,看看他的时间戳是否正确。(*是我为了不暴露ip代替了真实数据)

ID:1739202***********
二进制:0001100000100010111000110101001000100110010000*******************
  • 我们取它的时间戳位置,2-41位

0|00110000010001011100011010100100010011001|0000000000000000000000
  • 把这串二进制转换为10进制

->1739202348086984704
  • 转换代码

timestamp - 1288834974657L << 22 = ?
timestamp - 1288834974657L = ? >> 22 
timestamp = ? >> 22 + 1288834974657L
  • 那么,这个"?"就是刚刚转换的值,将它算出来

  • OK,将后三位去掉,只取秒级的时间戳

  • 得出的时间完美符合数据创建时间,但也许id中的更加准确,到了毫秒

  • 同理,按照源代码来也可以得出workID,IP等信息!

  • 14
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值