包含时间顺序的ID

此场景最简单的实现方案,就是采用 twitter 的 Snowflake 算法。
ID总长64位,第1位不可用,41位表示时间戳,10位表示生成机器的id,后12位表示序列号。

  • 为什么第一位不可用?第一位为0,可以确保ID在java的long类型数据一直为正整数递增
  • 同一时间戳即毫秒内,能产生多少个ID? 2^12 = 4096 个ID [ 0 ~ 4095 ]
  • 唯一性?通过机器ID预先已经做了一次空间隔离,再通过时间戳做了一次时间隔离,最后通过时间戳内的计数实现了一定程度内的唯一
  • 高性能?可以通过增加IDWorker来缓解高并发时的单机负载压力
  • 缺点?时间受限,41位可以表示69年(不过可以减少机器位来增加时间位数)

自增序列

原理

根据key获取分布式锁,获得锁后取得序号,并偏移配置的偏移量,替换原先的序号,最后释放锁。

基于zookeeper实现

基于zookeeper可以很快实现自增序列服务,引入apache的curator封装的zookeeper客户端。

1
2
3
4
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
</dependency>

建立zookeeper连接,打开zkclient后,如果重复会使用,可以将其放入全局map中,作统一管理。

address:zookeeper的地址
RetryNTimes:重连策略(重连重试次数,重连间隔毫秒)

1
2
CuratorFramework zkClient =  CuratorFrameworkFactory.newClient(address,new RetryNTimes(10, 5000));
zkClient.start();

获取分布式锁
按照业务逻辑,选择合适的锁,此处用的是可重入共享锁,即一个客户端在拥有锁的同时,可以再请求获取。

大专栏  分布式全局唯一ID与自增序列="gutter">
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
InterProcessMutex lock = new InterProcessMutex(zkClient, lockPath);
try {
if (lock.acquire(time, unit)) {
consumer.accept(lockPath);
return true;
}
return false;
} catch (Exception e) {
logger.error(e.getMessage(), e);
} finally {
try {
lock.release();
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
}
return false;

获取下个序号
判断序列名称是否已经存在,如果不存在创建,存在则增加step并写入

creatingParentsIfNeeded:当zk节点的父级不存在的时候,迭代创建
sequenceName:序列名称
step:自增步长

1
2
3
4
5
6
7
8
9
String path = "/seq/"+sequenceName;
boolean exists = zkClient.checkExists().forPath(path) != null;
if (!exists) {
zkClient.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).forPath(path, (step + "").getBytes());
} else {
byte[] bytes = zkClient.getData().forPath(path);
Long seq = Long.valueOf(new String(bytes));
zkClient.setData().forPath(path, (seq + step + "").getBytes());
}

因为需要实时修改zookeeper的节点信息,可以考虑建立序列池,例如直接取走10000个序列,由各个服务内部自己去生成,具体实现主要依赖到CAS,通过compareAndSet去实现单机内部的序号递增,避免锁的滥用

分布式全局唯一ID与自增序列的更多相关文章

  1. 分布式全局唯一ID生成策略

    为什么分布式系统需要用到ID生成系统 在复杂分布式系统中,往往需要对大量的数据和消息进行唯一标识.如在美团点评的金融.支付.餐饮.酒店.猫眼电影等产品的系统中,数据日渐增长,对数据库的分库分表后需要有 ...

  2. 框架篇:分布式全局唯一ID

    前言 每一次HTTP请求,数据库的事务的执行,我们追踪代码执行的过程中,需要一个唯一值和这些业务操作相关联,对于单机的系统,可以用数据库的自增ID或者时间戳加一个在本机递增值,即可实现唯一值.但在分布 ...

  3. Mysql系列七:分库分表技术难题之分布式全局唯一id解决方案

    一.前言 在前面的文章Mysql系列四:数据库分库分表基础理论中,已经说过分库分表需要应对的技术难题有如下几个: 1. 分布式全局唯一id 2. 分片规则和策略 3. 跨分片技术问题 4. 跨分片事物 ...

  4. 分布式全局唯一ID的实现

    分布式全局唯一ID的实现 前言 上周末考完试,这周正好把工作整理整理,然后也把之前的一些素材,整理一番,也当自己再学习一番. 一方面正好最近看到几篇这方面的文章,另一方面也是正好工作上有所涉及,所以决 ...

  5. (4.24)【mysql、sql server】分布式全局唯一ID生成方案

    参考:分布式全局唯一ID生成方案:https://blog.csdn.net/linzhiqiang0316/article/details/80425437 分表生成唯一ID方案 sql serve ...

  6. 分布式全局唯一ID

    方案一.UUID UUID的方式能生成一串唯一随机32位长度数据,它是无序的一串数据,按照开放软件基金会(OSF)制定的标准计算,UUID的生成用到了以太网卡地址.纳秒级时间.芯片ID码和许多可能的数 ...

  7. 常见分布式全局唯一ID生成策略

    全局唯一的 ID 几乎是所有系统都会遇到的刚需.这个 id 在搜索, 存储数据, 加快检索速度 等等很多方面都有着重要的意义.工业上有多种策略来获取这个全局唯一的id,针对常见的几种场景,我在这里进行 ...

  8. 分布式全局唯一ID生成策略​

    一.背景 分布式系统中我们会对一些数据量大的业务进行分拆,如:用户表,订单表.因为数据量巨大一张表无法承接,就会对其进行分库分表. 但一旦涉及到分库分表,就会引申出分布式系统中唯一主键ID的生成问题. ...

  9. redis 学习笔记3(哨兵模式下分布式锁的实现以及全局唯一id的生成)

    redis实现分布式锁和全局唯一id应该是较为常见的应用. 实现基于redis的setNX,以及incr命令.还是比较简单的! 搭建环境以及配置好sping整合,做了下测试,有兴趣的载下来看看,自己做 ...

随机推荐

  1. aliyun服务器lamp配置

    1.安装Apache:yum install httpd 2.安装php: yum install php 3.安装mysql客户端:yum install mysql 4.安装mysql服务端:yu ...

  2. 吴裕雄--天生自然MySQL学习笔记:MySQL 删除数据库

    使用普通用户登陆 MySQL 服务器,可能需要特定的权限来创建或者删除 MySQL 数据库,所以使用 root 用户登录,root 用户拥有最高权限. 在删除数据库过程中,务必要十分谨慎,因为在执行删 ...

  3. linux环境java程序cpu爆表问题查证

    1.top命令查找导致cup爆表的进程 2. top -H -p10832 (10832是Java进程的PID)命令找出了具体的线程 3.使用用命令 jstack 10832> jstack.t ...

  4. 向mysql数据库中插入数据时显示“Duplicate entry '1′ for key ‘PRIMARY' ”错误

    错误情况如题,出现这个错误的原因十分简单: 很明显,这是主键的问题. 在一张数据表中是不能同时出现多个相同主键的数据的 这就是错误的原因,解决的方法: 1.可以将这张表设置成无主键(mysql支持,其 ...

  5. [CF百场计划]#3 Educational Codeforces Round 82 (Rated for Div. 2)

    A. Erasing Zeroes Description You are given a string \(s\). Each character is either 0 or 1. You wan ...

  6. 拉格朗日乘子(Lagrange multify)和KKT条件

    拉格朗日乘子(Lagrange multify)和KKT条件 无约束问题 无约束问题定义如下: f(x)称为目标函数, 其中x是一个向量,它的维度是任意的. 通过求导, 令导数等于零即可: 如下图所示 ...

  7. Python批量重命名文件

    批量替换文件名中重复字符: # -*- coding: UTF-8 -*- import os path = raw_input("请输入文件夹路径:") oldname = ra ...

  8. Ubuntu---gedit 打开windows 下 .txt 文件乱码的解决方法

    问题出现情况:在windows 下编辑的 .txt 文件复制到 Ubuntu 下打开,默认打开方式为 gedit 软件打开,出现如下乱码: 出现原因:在 windows 系统下,.txt 文件默认编码 ...

  9. SVN提交时忽略不必提交的文件夹和文件,如node_modules

    空白处右键>选中TortoiseSVN>设置(settings)>常规设置(General)>Subversion>编辑(edit)>在弹出的config文件中找g ...

  10. LGOJ4172 WC2006水管局长

    首先声明,这份代码空间复杂度 \(O(n^2)\),瓶颈在给边打标记 由于博主太菜,懒得再改成低复杂度的打标记了,所以\(BZOJ\)的数据过不去 Description link 给一张图,会有删边 ...