高并发情况下分布式全局ID

java生成唯一id(uuid)(不依赖jdk5,自己实现的) NULL 博文链接:https://jarorwar.iteye.com/blog/553875 立即下载

高并发情况下分布式全局ID

 

 

1、高并发情况下,生成分布式全局id策略
2、利用全球唯一UUID生成订单号优缺点
3、基于数据库自增或者序列生成订单号
4、数据库集群如何考虑数据库自增唯一性
5、基于Redis生成生成全局id策略
6、Twitter的Snowflake算法生成全局id
7、基于Zookeeper生成全局id

 

 

高并发情况下,生成分布式全局id策略

1、注意幂等性且全局唯一性
2、注意安全性,不能被猜疑
3、趋势递增性

订单号命名规则:比如“业务编码 + 时间戳 + 机器编号[前4位] + 随机4位数 + 毫秒数”。

 

利用全球唯一UUID生成订单号
UUID基本概念:
UUID是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的。
UUID组成部分:当前日期和时间+时钟序列+随机数+全局唯一的IEEE机器识别号
全局唯一的IEEE机器识别号:如果有网卡,从网卡MAC地址获得,没有网卡以其他方式获得。
UUID优缺点:
优点:
简单,代码方便
生成ID性能非常好,基本不会有性能问题
全球唯一,在遇见数据迁移,系统数据合并,或者数据库变更等情况下,可以从容应对
缺点:
没有排序,无法保证趋势递增
UUID往往是使用字符串存储,查询的效率比较低
存储空间比较大,如果是海量数据库,就需要考虑存储量的问题。
传输数据量大

 

UUID不需要联网生成,redis需要。

 

基于数据库自增方式

实现思路:利用数据库自增或者序列号方式实现订单号
注意:在数据库集群环境下,默认自增方式存在问题,因为都是从1开始自增,可能会存在重复,应该设置每台不同数据库自增的间隔方式不同。
优点:
简单,代码方便,性能可以接受。
数字ID天然排序,对分页或者需要排序的结果很有帮助。
缺点:
不同数据库语法和实现不同,数据库迁移的时候或多数据库版本支持的时候需要处理。
在性能达不到要求的情况下,比较难于扩展。
在单个数据库或读写分离或一主多从的情况下,只有一个主库可以生成。有单点故障的风险。
分表分库的时候会有麻烦。

 

数据库集群如何考虑数据库自增唯一性

在数据库集群环境下,默认自增方式存在问题,因为都是从1开始自增,可能会存在重复,应该设置每台节点自增步长不同。
查询自增的步长
SHOW VARIABLES LIKE 'auto_inc%'
修改自增的步长
SET @@auto_increment_increment=10;    
修改起始值
SET @@auto_increment_offset=5;
假设有两台mysql数据库服务器
节点①自增 1 3 5 7 9 11 ….
节点②自增 2 4 6 8 10 12 ….
注意:在最开始设置好了每台节点自增方式步长后,确定好了mysql集群数量后,无法扩展新的mysql,不然生成步长的规则可能会发生变化。

 

MySQL1    1 2 3

MySQL2    1 2 3

  方法1   读写分离

  方法2  设置自增步长        需要提前设置好步长  否则如果新增一台MySQL就麻烦了

             如果想提高扩展性 采用UUID方式作为主键

 

 

基于Redis生成生成全局id策略
因为Redis是单线的,天生保证原子性,可以使用Redis的原子操作 INCR和INCRBY来实现
优点:
不依赖于数据库,灵活方便,且性能优于数据库。
数字ID天然排序,对分页或者需要排序的结果很有帮助。
缺点:
如果系统中没有Redis,还需要引入新的组件,增加系统复杂度。
需要编码和配置的工作量比较大。
注意:在Redis集群情况下,同样和Redis一样需要设置不同的增长步长,同时key一定要设置有效期
可以使用Redis集群来获取更高的吞吐量。假如一个集群中有5台Redis。可以初始化每台Redis的值分别是1,2,3,4,5,然后步长都是5。各个Redis生成的ID为:
A:1,6,11,16,21
B:2,7,12,17,22
C:3,8,13,18,23
D:4,9,14,19,24
E:5,10,15,20,25


比较适合使用Redis来生成每天从0开始的流水号。比如订单号=日期+当日自增长号。可以每天在Redis中生成一个Key,使用INCR进行累加。

如果生成的订单号超过自增增长的话,可以采用前缀+自增+并且设置有效期

 

 

当前日期-5位自增

统一时间 最多生成10w-1个不重复的

 

假设双十一 每秒99w订单

   

package com.toov5.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class OrderController {
    @Autowired
    private RedisTemplate redisTemplate;
    
   @RequestMapping("/order")    
   public Long order(String key) {
       
       RedisAtomicLong redisAtomicLong = new RedisAtomicLong(key, redisTemplate.getConnectionFactory() );
       long andIncrement = redisAtomicLong.getAndIncrement();
       return andIncrement;
       
   }
}

 补零:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class OrderController {
    @Autowired
    private RedisTemplate redisTemplate;
    
   @RequestMapping("/order")    
   public String order(String key) {
       
       RedisAtomicLong redisAtomicLong = new RedisAtomicLong(key, redisTemplate.getConnectionFactory() );
       long increment = redisAtomicLong.getAndIncrement();
       String id = String.format("%1$05d", increment);  //5位数
       return id;
       
   }
}

 

 

 加上前缀:

import java.text.SimpleDateFormat;
import java.util.Date;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class OrderController {
    @Autowired
    private RedisTemplate redisTemplate;
    
   @RequestMapping("/order")    
   public String order(String key) {
       
       RedisAtomicLong redisAtomicLong = new RedisAtomicLong(key, redisTemplate.getConnectionFactory() );
       long increment = redisAtomicLong.getAndIncrement();
       String id =prefix()+"-"+String.format("%1$05d", increment);  //5位数
       return id;
       
   }
   
   public static String prefix() {
        String temp_str = "";
        Date dt = new Date();
        // 最后的aa表示“上午”或“下午” HH表示24小时制 如果换成hh表示12小时制
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        temp_str = sdf.format(dt);
        return temp_str;
    }
}

 

   

 

 

 Redis如果做集群,会产生重复的问题!
   

@RequestMapping("/order1")
    public String order1(String key) {
        RedisAtomicLong redisAtomicLong = new RedisAtomicLong(key, redisTemplate.getConnectionFactory());
        // // 起始值
        // redisAtomicLong.set(10);
        // 设置步长加10!!!!
        redisAtomicLong.addAndGet(9);
        return redisAtomicLong.incrementAndGet() + "";
    }

 

 redis 的key的失效时间问题!

   24h  第二天时间变了 不会重复了哦

 

 

Twitter的snowflake(雪花)算法  (跟UUID一样不用联网)
snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是:
高位随机+毫秒数+机器码(数据中心+机器id)+10位的流水号码
Github地址: https://github.com/twitter-archive/snowflake
Snowflake 原理:
snowflake生产的ID是一个18位的long型数字,二进制结构表示如下(每部分用-分开):
0 - 00000000 00000000 00000000 00000000 00000000 0 - 00000 - 00000 - 00000000 0000
第一位未使用,接下来的41位为毫秒级时间(41位的长度可以使用69年,从1970-01-01 08:00:00),然后是5位datacenterId(最大支持2^5=32个,二进制表示从00000-11111,也即是十进制0-31),和5位workerId(最大支持2^5=32个,原理同datacenterId),所以datacenterId*workerId最多支持部署1024个节点,最后12位是毫秒内的计数(12位的计数顺序号支持每个节点每毫秒产生2^12=4096个ID序号).所有位数加起来共64位,恰好是一个Long型(转换为字符串长度为18).单台机器实例,通过时间戳保证前41位是唯一的,分布式系统多台机器实例下,通过对每个机器实例分配不同的datacenterId和workerId避免中间的10位碰撞。最后12位每毫秒从0递增生产ID,再提一次:每毫秒最多生成4096个ID,每秒可达4096000个。

 

全局自增ID设计方案 在大型互联网应用中,随着用户数的增加,为了提高应用的性能,我们经常需要对数据库进行分库分表操作。在单表时代,我们可以完全依赖于数据库的自增ID来唯一标识一个用户或数据对象 立即下载

相关推荐

分布式系统从服务器获取时间

一个服务器,若干客户端,java rmi实现客户端从服务器获取当前时间

分布式主键生成算法

这篇文章总结了分布式主键或者唯一键的生成算法,文章最后有我们基于snowflow算法的思考和实践。 分布式主键的生成方式分为中心化和去中心化两大类。 中心化生成算法 中心化生成算法经典的方案主要有基于SEQUENCE区间方案、各数据库按特定步长自增和基于redis生成自增序列三种 SEQUENCE区间方案 淘...

weixin_34261415的博客 468

SpringBoot与Flowable整合:构建高效审批工作流的实战指南

本文是一份SpringBoot与Flowable整合构建高效审批工作流的实战指南。通过一个经典的二级审批场景,详细介绍了从项目搭建、BPMN流程设计、核心服务编写到RESTful API构建的完整步骤。文章深入探讨了如何利用Flowable工作流引擎实现审批流程的自动化驱动与灵活管理,并分享了变量管理、监听器、异步执行等进阶技巧与常见避坑指南,帮助开发者快速构建健壮、可维护的企业级审批系统。

qsc9012345的博客 519

分布式数据库主键:雪花算法

snowflake 算法 snowflake 算法是 twitter 开源的分布式 id生成算法,就是把一个 64 位的 long 型的 id,1 个 bit 是不用的,用其中的 41 bit 作为毫秒数,用 10 bit 作为工作机器 id,12 bit 作为序列号。 1 bit:不用,为啥呢?因为二进制里第一个 bit 为如果是 1,那么都是负数,但是我们生成的 id 都是正数,所以第一...

TuoLinHuai的博客 3197

Synology-群晖(三)DSM7.0系统Video Station无法播放DTS eac3解决方案

群晖升级DSM7.0后,发现部分DTS eac3解码的视频无法通过Vedio Station 3.0.1-2067进行播放,提示不支持该格式视频,初步判断是无法加载ffmpeg解码导致,网上搜了很多处理办法都没有办法解决,最终在知乎上看到一片文章,按此办法解决了这个问题,目前经过验证,该方案完美支持最新版本Video Station 3.0.1-2067,验证系统为DSM7.0和DSM7.0.1,这里使用的NAS为 Vmware虚拟机 黑群晖 演示。大概步骤如下: 添加这个社群来源 http://p

weixin_45827203的博客 3万+

使用 VPN 访问太理内部网相关问题总结【太原理工大学】

电脑连接 VPN,访问校园内部网相关问题总结,太原理工大学。

m0_52861684的博客 9880

java id主键_JAVA主键ID生成工具类:改自twitter的分布式ID算法snowflake

祝大家新年快乐,有任何问题可与我联系:关于snowflake算法的介绍和原理这里不过多说明了,网上有很多。这里简单描述下SnowflakeUtil的优点:1、做为底层工具使用,可用于数据库主键、订单编号……2、不依赖数据库,速度快3、可有序生成4、可分布式部署当然缺点也是有的,我相信看了下面SnowflakeUtil的朋友自然能够明白。下面是SnowflakeUtil类的代码:package cn...

weixin_32144483的博客 402

C语言图形化界面——含图形、按钮、鼠标、进度条等部件制作(带详细代码、讲解及注释)

本文借助easyx库函数(提供下载链接),很方便地用C语言实现了鼠标、按钮、进度条、坐标尺等操作,为普通C程序的友好人机交互界面提供了一种简单便捷的方案。

体会编程语言独到的美 17万+

分布式系统--主键id的选择

介绍了分布式系统下几种常见的主键策略的优劣性

Jimmy_Lyu的博客 638

AI 生成 CAN 通信测试用例实战

本文分享了AI辅助汽车电子测试用例编写的实战经验。通过某车企CAN网络测试项目案例,对比传统方式(需27天)与AI辅助方式(仅5天)的效率差异,展示81%的效率提升。文章详细介绍了从DBC文件提取信号信息的方法,包括DBC文件结构解析、信号定义说明,并提供了完整的Python解析脚本代码,可将信号信息导出为JSON或Excel格式,为后续AI批量生成测试用例奠定基础。

小明的博客 693

Creo二次开发环境配置与DLL项目实战指南(Creo8.0+VS2019)

本文详细介绍了Creo8.0与VS2019环境下的二次开发配置与DLL项目实战指南,涵盖环境准备、版本匹配、DLL项目创建、核心代码编写、部署调试及常见报错处理。重点解析了Creo二次开发中的关键配置和优化技巧,帮助开发者高效解决实际问题。

weixin_28432777的博客 517

Java分布式ID

分布式ID

zhangyan_1010的专栏 1824

模拟滤波器的基础知识和设计

使用Python实现多种模拟滤波器

faltas的博客 3530

分布式高并发情况下全局Id生成策略

分布式高并发情况下全局Id生成策略 一、高并发情况下,生成分布式全局id策略需注意 注意幂等性且全局唯一性 注意安全性,不能被猜疑 趋势递增性 二、利用全球唯一UUID生成订单号 UUID基本概念: UUID是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的。 UUID组成部分: 当前日期和时间+时钟序列+随机数+全局唯一的IEEE机器识别号全局唯一的IEEE机器识别号:如果有网卡,从网卡MAC地址获得,没有网卡以其他方式获得。 UUID优缺点: 优点: 简单,代码方便生成ID性能

小毕超博客 3071

K8s(十二):监控与报警(163邮箱+钉钉)-Prometheus + Grafana + Alertmanager(超详细)

🔴 K8s(十二):监控与报警(163邮箱+钉钉)-Prometheus + Grafana + Alertmanager(超详细)

✨ 欢迎来到【Seal ^_^ 的优快云博客】!✨ 3万+

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

集群高并发情况下如何保证分布式唯一全局Id生成

集群高并发情况下如何保证分布式唯一全局Id生成问题为什么需要分布式全局唯一ID以及分布式ID的业务需求ID生成规则部分硬性要求ID号生成系统的可用性要求一般通用解决方案UUID存在问题数据库自增主键单机集群分布式集群基于Redis生成全局ID策略单机版集群分布式雪花算法是什么结构第一部分第二部分第三部分第四部分SnowFlake可以保证实现工程落地经验hutools工具包SpringBoot整合雪花算法优缺点优点缺点其它补充 问题 为什么需要分布式全局唯一ID以及分布式ID的业务需求 在复杂分布式系统中,往

轻狂书生FS的博客 3400

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

高并发情况下分布式全局Id生成

全局id生成 高并发情况下,生成分布式全局id策略 1、注意幂等性且全局唯一性 2、注意安全性,不能被猜疑 3、趋势递增性 订单号命名规则:比如“业务编码 + 时间戳 + 机器编号[前4位] + 随机4位数 + 毫秒数”。 1、利用全球唯一UUID生成订单号优缺点 1.1 从利用全球唯一UUID生成订单号 UUID基本概念: UUID是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的。 UUID组成部分:当前日期和时间+时钟序列+随机数+全局唯一的IEEE机器识别号 全局唯一的IEEE机器

qq_39380737的博客 349

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

mysql 分布式 全局ID_高并发情况下分布式全局ID

1、高并发情况下,生成分布式全局id策略2、利用全球唯一UUID生成订单号优缺点3、基于数据库自增或者序列生成订单号4、数据库集群如何考虑数据库自增唯一性5、基于Redis生成生成全局id策略6、Twitter的Snowflake算法生成全局id7、基于Zookeeper生成全局id高并发情况下,生成分布式全局id策略1、注意幂等性且全局唯一性2、注意安全性,不能被猜疑3、趋势递增性订单号命名规则...

weixin_39633113的博客 260

集群、分布式 高并发的情况下如何生成全局唯一ID

集群高并发的情况下如何生成全局唯一ID 1,ID生成规则的硬性要求: 全局唯一 趋势递增 单调递增 信息安全 含时间戳 2,ID生成系统的可用性要求: 高可用 低延迟 高QPS:10万个的请求同时过来。 3,生成全局唯一ID的主要方案: 中间件方式:可以通过数据库或 redis 缓存作为媒介,通过数据库生成自增ID来作为唯一ID。数据库的自增ID机制的原理是:数据库自增ID的mysql 的 repalce into 实现的(没有新增有则替换,字段创建唯一索引),缺点:系统水平扩展困难,依赖中间件

不负年华 1625

高并发情况下分布式全局Id生成4种方案

1.利用全球唯一UUID生成订单号 UUID是一个字符串而且没有顺序,所以不适合做主键,可以 做 token 使用。 利用全球唯一UUID生成订单号 UUID基本概念: UUID是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的。 UUID组成部分:当前日期和时间+时钟序列+随机数+全局唯一的IEEE机器识别号 全局唯一的IEEE机器识别号:如果有网卡,从网卡MAC地址获得,没有网卡以其他方式获得。 优点:简单,代码方便 生成ID性能非常好,基本不会有性能问题 全球唯一,在..

jiayoubing的专栏 678

集群高并发情况下如何保证分布式唯一全局ID生成

一、问题 1、为什么需要分布式全局唯一ID以及分布式ID的业务需求 在负载分布式系统中,往往需要对大量的数据和消息进行唯一标识。 如在美团点评的金融、支付、餐饮、酒店;猫眼电源等产品的系统中数据日渐增长,对数据分库分表后需要有一个唯一ID来标识一条数据或消息。 特别一点如订单、骑手优惠券也需要有唯一ID做标识。 此时一个能生成全局唯一ID的系统是非常必要的。 2、ID生成规则部分硬性要求 全局唯一:不能出现重复的ID 趋势递增:在 Mysql 的 InnoDB 中使用的是聚集索引,由于多数

chenjian723122704的专栏 1137

高并发情况下,如何生成分布式全局id

1.使用UUID生成全局id UUID是一个字符串而且没有顺序,所以不适合做主键,可以 做 token 使用。 利用全球唯一UUID生成订单号 UUID基本概念: UUID是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的。 UUID组成部分:当前日期和时间+时钟序列+随机数+全局唯一的IEEE机器识别号 全局唯一的IEEE机器识别号:如果有网卡,从网卡MAC地址...

dianbiao3588的博客 221

集群高并发情况下如何保证分布式唯一全局id生成

一、问题 1.1 为什么需要分布式全局唯一ID以及分布式ID的业务需求 ?   在复杂分布式系统中,往往需要对大量的数据和消息进行唯一标识。如在美团点评的金融、支付、餐饮、酒店;猫眼电影等产品的系统中数据日渐增长,对数据分库分表后需要有一个唯一ID来标识一 条 数据或消息;特别一点的如订单、骑手、优惠券也都需要有唯一ID做标识。此时一个能够生成全局唯一ID的系统是非常必要的。 1.2 ID生成规则部分硬性要求 全局唯一:不能出现重复的ID号,既然是唯一标识,这是最基本的要求 趋势递增:在MySQL的inn

FireCode的博客 1664
上一篇: Spring Cloud2.0之Oauth2环境搭建(授权码模式和密码授权模式)
下一篇: MySQL高可用
Art&Code
博客等级 码龄7年 77粉丝 554原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值