分布式唯一ID

分布式ID的主要需求就是保证在分布式的多机器环境下保证id是唯一的。其次是高可用、如果要存在数据库中最高是有序递增并且带有时间信息。

唯一性方案:

uuid:

uuid的底层是一组32位数的16进制数字构成,,生成过程要用到mac地址、时间戳、芯片ID码和随机数等,理论上几亿年都用不完。

return UUID.randomUUID().toString().replace("-","");

业务场景:

我们公司OA系统里面每个人的唯一id就是uuid。实际场景中拿uuid当主键的好处是避免id有序被别人破解。就像我们公司oa里面每个人照片的下载链接后缀参数都是uuid,如果不是uuid而是有序的id会被直接爬取下载。其他业务场景可以拿去当普通资源的兑换码去使用,比如说网站做一些小活动送优惠卷了,可以当作卡券兑换码之类的。

唯一性+有序+时间:

涉及到数据库的方案,一般都是pass。系统都开始用分布式系统了,数据库肯定也集群了,再去使用数据库帮忙有点本末倒置了。

redis方案:

目前公司通过Redis自增命令与时间戳相结合来提供线程安全的分布式唯一标识符生成策略。原理就是通过redis的原子性自增命令(单线程)+时间戳+填充的数字(高位补0、自己填一部分、随机数)组成一个32位的数字。

// 再填充一些时间和其他数字信息
return jedis.incr("id");

业务场景:做订单号,数据库表主键。
 

zookeeper方案:

通过创建临时节点来完成,不同客户端每次只能一个创建节来获取节点path来得到唯一id。

return zooKeeper.create("/id", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL).substring(3);

业务场景:做订单号,数据库表主键。

雪花算法:

1位符号位+41位时间戳+10位数据机器位+12位毫秒内的序列。机器位是机房id+机房里面服务器id凑的,后面序列是保证1s内多并发。

return ((timestamp - twepoch) << timestampLeftShift) |
                (datacenterId << datacenterIdShift) |
                (workerId << workerIdShift) |
                sequence;

可能还有其他大厂提供的组件,但原理以及涉及的组件和上面方案差不多。

// 4类方案代码
https://gitee.com/mjTree/javaDevelop/tree/master/distributed/分布式ID

贝氏倭狐猴

    贝氏倭狐猴????:体长9-11厘米,尾长12-14厘米,体重30克。这个物种具有非常大的前向眼睛,具有很强的夜视功能。上体毛皮呈红棕色,背部的中线有一条黑色条纹延伸至尾部。下体毛皮是奶油色或浅灰色。头部有明显的标记,鼻子上方有一个沉闷的白色斑块,眼睛周围有肉桂环。像其他的倭狐猴一样,有一条长尾巴,耳朵比较大并裸露无毛。

    它们出没于潮湿的热带雨林,树栖,群居,通常结对生活在小溪或河边。以水果和虫子为主食。白天躲在树洞中,傍晚时等到日落才会活都,是一种在夜间活动的孤独者。通过树木和低层植被,寻找昆虫、水果、壁虎和变色龙等小型爬行动物。它们主要食物来源是由蛾蜡蝉幼虫产生的含糖分泌物(或称“蜜露”)。由于非法采伐木材造成的栖息地遭到破坏以及农业扩张,该物种有灭绝的危险。

2014年濒危物种红色名录ver3.1——濒危(EN)。 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Java分布式唯一ID生成方案有很多种,其中一种比较常用的方案是基于Snowflake算法的ID生成方案。 Snowflake算法是一种基于时间序列生成唯一ID的算法,它可以在分布式系统中生成唯一的、有序的、趋势递增的ID。Snowflake算法生成的ID是一个64位的整数,它的结构如下: ``` 0 - 41位时间戳 - 10位机器标识 - 12位序列号 ``` 其中,时间戳占用了41位,可以表示2^41-1个数字,大约可以支持生成69年的ID;机器标识占用了10位,可以表示1023个不同的机器;序列号占用了12位,可以表示4095个不同的序列号。 Snowflake算法的实现比较简单,可以使用Java的AtomicLong类来实现序列号的自增。具体的实现可以参考下面的代码: ```java public class SnowflakeIdGenerator { private static final long START_TIMESTAMP = 1577808000000L; // 2020-01-01 00:00:00 private static final long MACHINE_ID_BITS = 10L; private static final long SEQUENCE_BITS = 12L; private static final long MACHINE_ID_OFFSET = SEQUENCE_BITS; private static final long TIMESTAMP_OFFSET = MACHINE_ID_BITS + SEQUENCE_BITS; private static final long MAX_MACHINE_ID = (1L << MACHINE_ID_BITS) - 1L; private static final long MAX_SEQUENCE = (1L << SEQUENCE_BITS) - 1L; private static long machineId = 0L; private static long sequence = 0L; private static long lastTimestamp = -1L; static { String machineName = ""; try { machineName = InetAddress.getLocalHost().getHostName(); } catch (UnknownHostException e) { e.printStackTrace(); } machineId = Math.abs(machineName.hashCode()) % MAX_MACHINE_ID; } public synchronized static long nextId() { long currentTimestamp = System.currentTimeMillis(); if (currentTimestamp < lastTimestamp) { throw new IllegalStateException("Clock moved backwards. Refusing to generate id"); } if (currentTimestamp == lastTimestamp) { sequence = (sequence + 1L) & MAX_SEQUENCE; if (sequence == 0L) { currentTimestamp = waitUntilNextMillis(currentTimestamp); } } else { sequence = 0L; } lastTimestamp = currentTimestamp; return ((currentTimestamp - START_TIMESTAMP) << TIMESTAMP_OFFSET) | (machineId << MACHINE_ID_OFFSET) | sequence; } private static long waitUntilNextMillis(long currentTimestamp) { while (currentTimestamp == lastTimestamp) { currentTimestamp = System.currentTimeMillis(); } return currentTimestamp; } } ``` 使用这个类可以生成全局唯一ID,可以在分布式系统中使用。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值