分布式系统下的唯一序列

分布式系统中,全网唯一序列号

作用:保证在分布式系统下,不同业务模块的业务操作独立性和唯一性,并且可适用于高并发场景。

常见业务场景:全局订单Id,唯一标识的支付编号等。

唯一序列的特征:

  全局唯一:确保生成的序列全局唯一,不可重复;

  有序递增:确保生成的序列对某个用户或业务是按序递增,如事务版本号、IM增量消息、排序等特殊需求;

  高可用性:确保生成的序列功能的高可用,能够承接较大峰值,能够保证序列生成的有效性(不重复且有序);

  时间标记:序列中有时间片段组成,可清晰识别出操作的时间。

分布式系统下的唯一序列的实现方案

1、UUID

UUID(Universally Unique Identifier)的标准型式包含32个16进制数字,以连字号分为五段,形式为8-4-4-4-12的36个字符,示例:550e8400-e29b-41d4-a716-446655440000

生成方式:

(1)UUID工具包

Maven依赖:

<dependency>
  <groupId>com.fasterxml.uuid</groupId>
  <artifactId>java-uuid-generator</artifactId>
  <version>4.0</version>
</dependency>

使用示例:

//UUID Version 1:基于时间的UUID(全球唯一)
UUID uuid1 = Generators.timeBasedGenerator().generate();

//UUID Version 3:基于名字的UUID(相关名字重复)
UUID uuid3 = Generators.nameBasedGenerator().generate("sai");

//UUID Version 4:随机UUID(java自带版本,极小概率重复)
UUID uuid4 = Generators.randomBasedGenerator().generate();

(2)Java的UUID工具类

复制代码
import java.util.UUID;

public class JavaUUIDTest {

    public static void main(String[] args) {

        //未加工的UUID
        String preUuid = UUID.randomUUID().toString();
        System.out.println(preUuid);

        //第一种方法生成UUID,去掉“-”符号
        System.out.println(UUID.randomUUID().toString().replace("-", ""));

        //未加工的UUID
        String preUuid2 = UUID.randomUUID().toString();
        System.out.println(preUuid2);
        //第二种生成UUID的方法,去掉“-”符号
        String changUuid = preUuid2.substring(0,8)+preUuid2.substring(9,13)+preUuid2.substring(14,18)+preUuid2.substring(19,23)+preUuid2.substring(24);

        System.out.println(changUuid);
    }
}
复制代码

优点:本地生成,无网络消耗,性能非常高。

缺点:太长不易于存储;无时间标识;数据可读性差;不能有序递增;基于MAC地址生成,可能造成MAC地址泄露。

2、数据库生成

数据库设置主键自增:

  MySQL:auto_increment

  Oracle:自增序列+触发器

优点:操作简单,明显可控,有序自增。

缺点:依赖数据库,不适于高并发。

3、系统时间戳

生成方式:当前系统时间(精确到毫秒数或时间戳)+业务属性+用户属性+随机数+...等参数组合形式。

例如:  滴滴:时间+起点编号+车牌号     淘宝订单:时间戳+用户ID

可保证唯一性,不能保证有序性。

4、Redis生成唯一序列

使用Redis的String类型,及原子操作 incr/decr key 来实现,保证生成系列唯一有序。

incr/decr key // 自增减 1
incrby/decrby key increment  // 自增减指定数值
incrbyfloat/decrbyfloat key increment
// 自增减浮点数

优点:有序自增;不依赖于数据库,灵活方便,性能优于数据库。

缺点:增加Redis维护成本(编码、配置等),高并发时需设置Redis集群。

另外,利用zookeeper的znode数据版本来生成序列号 和 MongoDB的ObjectId 性能不如Redis。

5、snowflake(雪花算法)

生成方式:通过把 64bit 分别划分成 41bit 时间戳、10bit 工作机器id、12bit 序列号 的不同的命名空间生成序列id。

  • 41位的时间序列,精确到毫秒,可以使用69年

  • 10位的机器标识,最多支持部署1024个节点

  • 12位的序列号,支持每个节点每毫秒产生4096个ID序号,最高位是符号位始终为0。

优点:

  • 毫秒数在高位,自增序列在低位,整个ID趋势递增。
  • 不依赖数据库等第三方系统,以服务的方式部署,稳定性更高,生成ID的性能非常高。
  • 可根据自身业务特性分配bit位,非常灵活。

缺点:强依赖机器时钟,若机器上时钟回拨,会导致发号重复或服务不可用。

6、UidGenerator

百度开源的一款分布式高性能的唯一ID生成器,Java实现, 基于Snowflake算法的唯一ID生成器。

GitHub:https://github.com/baidu/uid-generator/blob/master/README.zh_cn.md

7、Leaf

美团开源的分布式ID生成器,能保证全局唯一性、趋势递增、单调递增、信息安全,同时也需要依赖关系数据库、Zookeeper等中间件。

美团技术社区详情说明:https://tech.meituan.com/2017/04/21/mt-leaf.html

参考:https://www.cnblogs.com/wzh2010/p/15642421.html

https://www.cnblogs.com/shoshana-kong/p/13854524.html

本文作者:青志暖阳、惜殇

本文链接:https://www.cnblogs.com/qzny/p/16376800.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   青志暖阳、惜殇  阅读(267)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
  1. 1 404 not found REOL
404 not found - REOL
00:00 / 00:00
An audio error has occurred.