关于分布式环境下的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做全局自增操作 优点:简单.高 ...
随机推荐
- shutil&shelve
https://www.cnblogs.com/xiangsikai/p/7787101.html http://www.cnblogs.com/wupeiqi/articles/4963027.ht ...
- 屏蔽eslint代码格式报错
1.在文件中找到node_modules 2.node_modules文件夹下的eslint-config-standard 3.打开eslint-config-standard文件夹下的eslint ...
- poj 1741
点分治入门题 首先发现是树上点对的问题,那么首先想到上点分治 然后发现题目要求是求出树上点对之间距离小于等于k的对数,那么我们很自然地进行分类: 对于一棵有根树,树上的路径只有两种:一种经过根节点,另 ...
- 下拉框、下拉控件之Select2。自动补全的使用
参考链接: 参考一:https://blog.csdn.net/weixin_36146275/article/details/79336158 参考二:https://www.cnblogs.com ...
- webpack分片chunk加载原理
首先,使用create-react-app快速创建一个demo npx create-react-app react-demo # npx命令需要npm5.2+ cd react-demo npm s ...
- io.lettuce.core.RedisCommandTimeoutException: Command timed out
遇到的情况是 redis timeout时间设置过短(我设置成0了),默认多少也查不到
- cmd命令中运行pytest命令导入模块报错解决方法
报错截图 ImportError while loading conftest 'E:\python\HuaFansApi\test_case\conftest.py'. test_case\conf ...
- MyBatis sqlsession 简化 使用工具类创建
2019-04-09 @Test public void Test() throws Exception { // 1.读取配置文件 String resource = "mybatis-c ...
- excel导出使用get请求参数过长问题
遇到的问题: excel导出功能时,使用的是window.location.href=url也就是get请求.当传入参数过长的时候就报了414,地址过长的错误. 解决思路: 将get请求换为post请 ...
- Git是什么、Git的功能、为什么versioncontrol用Git、Git的常用命令、Git的优缺点
Git是什么 git是目前世界上最先进的分布式版本控制系统(没有之一). Git是用于 Linux内核开发的版本控制工具.与常用的版本控制工具 CVS, Subversion 等不同,它采用了分布式版 ...