关于分布式环境下的id生成
- public class IdWorker
- {
- //基准时间
- public const long Twepoch = 1288834974657L;
- //机器标识位数
- private const int WorkerIdBits = ;
- //数据标志位数
- private const int DatacenterIdBits = ;
- //序列号识位数
- private const int SequenceBits = ;
- //机器ID最大值
- private const long MaxWorkerId = -1L ^ (-1L << WorkerIdBits);
- //数据标志ID最大值
- private const long MaxDatacenterId = -1L ^ (-1L << DatacenterIdBits);
- //序列号ID最大值
- private const long SequenceMask = -1L ^ (-1L << SequenceBits);
- //机器ID偏左移10位
- private const int WorkerIdShift = SequenceBits;
- //数据ID偏左移15位
- private const int DatacenterIdShift = SequenceBits + WorkerIdBits;
- //时间毫秒左移20位
- public const int TimestampLeftShift = SequenceBits + WorkerIdBits + DatacenterIdBits;
- private static readonly DateTime Jan1St1970 = new DateTime
- (, , , , , , DateTimeKind.Utc);
- private readonly object _lock = new object();
- private long _lastTimestamp = -1L;
- public IdWorker(long workerId, long datacenterId, long sequence = 0L)
- {
- // 如果超出范围就抛出异常
- if (workerId > MaxWorkerId || workerId < )
- throw new ArgumentException(string.Format("worker Id 必须大于0,且不能大于MaxWorkerId: {0}", MaxWorkerId));
- if (datacenterId > MaxDatacenterId || datacenterId < )
- throw new ArgumentException(string.Format("datacenterId Id 必须大于0,且不能大于MaxWorkerId: {0}",
- MaxDatacenterId));
- //先检验再赋值
- WorkerId = workerId;
- DatacenterId = datacenterId;
- Sequence = sequence;
- }
- public long WorkerId { get; protected set; }
- public long DatacenterId { get; protected set; }
- public long Sequence { get; internal set; }
- public virtual long NextId(long dataNode=)
- {
- lock (_lock)
- {
- if (dataNode > MaxDatacenterId || dataNode < )
- throw new ArgumentException($"dataNode 必须大于0,且不能大于MaxWorkerId: {MaxDatacenterId}");
- if (dataNode == )
- dataNode = DatacenterId;
- var timestamp = TimeGen();
- if (timestamp < _lastTimestamp)
- throw new Exception($"时间戳必须大于上一次生成ID的时间戳. 拒绝为{_lastTimestamp - timestamp}毫秒生成id");
- //如果上次生成时间和当前时间相同,在同一毫秒内
- if (_lastTimestamp == timestamp)
- {
- //sequence自增,和sequenceMask相与一下,去掉高位
- Sequence = (Sequence + ) & SequenceMask;
- //判断是否溢出,也就是每毫秒内超过1024,当为1024时,与sequenceMask相与,sequence就等于0
- if (Sequence == )
- timestamp = TilNextMillis(_lastTimestamp);
- }
- else
- {
- //如果和上次生成时间不同,重置sequence,就是下一毫秒开始,sequence计数重新从0开始累加,
- //为了保证尾数随机性更大一些,最后一位可以设置一个随机数
- Sequence = ; //new Random().Next(10);
- }
- _lastTimestamp = timestamp;
- return ((timestamp - Twepoch) << TimestampLeftShift) | (dataNode << DatacenterIdShift) |
- (WorkerId << WorkerIdShift) | Sequence;
- }
- }
- /// <summary>
- /// 防止产生的时间比之前的时间还要小(由于NTP回拨等问题),保持增量的趋势.
- /// </summary>
- /// <param name="lastTimestamp"></param>
- /// <returns></returns>
- protected virtual long TilNextMillis(long lastTimestamp)
- {
- var timestamp = TimeGen();
- while (timestamp <= lastTimestamp)
- timestamp = TimeGen();
- return timestamp;
- }
- /// <summary>
- /// 获取当前的时间戳
- /// </summary>
- /// <returns></returns>
- protected virtual long TimeGen()
- {
- return (long) (DateTime.UtcNow - Jan1St1970).TotalMilliseconds;
- }
- }
- public void GetId()
- {
- new IdWorker(, ).NextId();
- }
关于分布式环境下的id生成的更多相关文章
- 分布式环境下的id生成方法
分布式环境下的id生成方法 前几天研究数据库分表分库的问题,其中有一个关键的地方就是生成唯一键的问题,假如数据表有1亿条数据,而且还在不断的增加,这里我们就需要考虑到分表分库,假设我们采用Hash ...
- 分布式环境下Unique ID生成方法
ID即标示符,在某个搜索域内能唯一标示其中某个对象.在关系型数据库中每个表都需要定义一个主键来唯一标示一条记录.为了方便一般都会使用一个auto_increment属性的整形数做为ID.因为数据库本身 ...
- 【融云分析】如何实现分布式场景下唯一 ID 生成?
◀背景▶ 对于一套分布式部署的 IM 系统,要求每条消息的 ID 要保证在集群中全局唯一且按生成时间有序排列.如何快速高效的生成消息数据的唯一 ID ,是影响系统吞吐量的关键因素.那么,融云是如何做到 ...
- MySQL分库分表环境下全局ID生成方案 转
在大型互联网应用中,随着用户数的增加,为了提高应用的性能,我们经常需要对数据库进行分库分表操作.在单表时代,我们可以完全依赖于数据库的自增ID来唯一标识一个用户或数据对象.但是当我们对数据库进行了分库 ...
- MySQL分库分表环境下全局ID生成方案
在大型互联网应用中,随着用户数的增加,为了提高应用的性能,我们经常需要对数据库进行分库分表操作.在单表时代,我们可以完全依赖于数据库的自增ID来唯一标识一个用户或数据对象.但是当我们对数据库进行了分库 ...
- 【转】MySQL分库分表环境下全局ID生成方案
转载一篇博客,里面有很多的知识和思想值得我们去思考. —————————————————————————————————————————————————————————————————————— 在大 ...
- 高并发环境下全局id生成策略
解决方案: 基于Redis的全局id生成策略:(推荐此方法) 基于雪花算法的全局id生成: https://www.cnblogs.com/kobe-qi/p/8761690.html 基于zooke ...
- Shiro权限管理框架(二):Shiro结合Redis实现分布式环境下的Session共享
首发地址:https://www.guitu18.com/post/2019/07/28/44.html 本篇是Shiro系列第二篇,使用Shiro基于Redis实现分布式环境下的Session共享. ...
- 分布式全局不重复ID生成算法
分布式全局不重复ID生成算法 算法全局id唯一id 在分布式系统中经常会使用到生成全局唯一不重复ID的情况.本篇博客介绍生成的一些方法. 常见的一些方式: 1.通过DB做全局自增操作 优点:简单.高 ...
随机推荐
- [原创] f2fs文件系统源代码分析 —— 基于3.8内核 (一)
作者:高翔 <esxgx@163.com>本文著作权归作者所有,请在转载引用时保留原文网址. 在全文开始,首先记录f2fs被3.8主线merge的mailing list:[GIT PUL ...
- luoguP1373 小a和uim之大逃离
DP专题 题目链接 思路 \(f[i][j][a][b][0/1]\)表示在\((i,j)\)这个格子,小a有a滴魔液,他的伙伴有b滴,上一步是小a(0)或者他的伙伴(1)吸取的魔液. (显然)数组开 ...
- webstorm Terminal 位置错乱解决方案
win+R 打开终端,右击属性->勾选使用旧版控制台->确定 ,再重启webstrom 即可.
- Restful 接口开发 完整版
准备: springboot ssm框架 项目结构:注意 Swagger2Config要和springboot的启动类放在同一级 //pom所需的依赖 <dependency> <g ...
- The Quad - Directory Explorer(一款四窗口的文件资源管理器)
官网:http://www.q-dir.com/ 参考这位兄弟的介绍:https://www.cnblogs.com/clso/p/4694486.html 一款四窗口的文件资源管理器.
- memcpy一种实现方法
#include<stdio.h> #include<stdlib.h> void* memncpy(void* dest, const void* src, int coun ...
- A页面跳转到B页面后打开指定tabs标签
A页面: <!DOCTYPE html><html lang="en" class="no-js"> <head> ...
- maven安装与环境变量配置
一.什么是maven Maven基于项目对象模型(POM Project Object Model),可以通过一小段描述信息(配置文件)来管理项目的构建.报告和文档的软件项目管理工具. 同时也是跨平台 ...
- 解决MongoDB登录的WARNING
解决MongoDB登录的WARNING 1.安装完成运行mongodb警告内容如下: 2019-01-17T15:41:50.578+0800 I CONTROL [initandlisten] ** ...
- Linux网络技术管理及进程管理
OSI七层模型和TCP/IP四层模型 OSI七层模型:OSI(Open System Interconnection)开放系统互连参考模型是国际标准化组织(ISO)制定的一个用于计算机或通信系统间互联 ...