zoukankan      html  css  js  c++  java
  • Twitter全局唯一ID生成算法

       测试:private static void TestIdWorker()
            {
                HashSet<long> set = new HashSet<long>();
                IdWorker idWorker1 = new IdWorker(0, 0);
                IdWorker idWorker2 = new IdWorker(1, 0);
                //762884413578018816
                //762884520121729024
                Stopwatch sw = new Stopwatch();
                sw.Start();
                for (int i = 0; i < 1; i++)
                {
                    long id = idWorker1.nextId();
                    set.Add(id);
                    //if (!set.Add(id))
                    //{
                    //Console.WriteLine("duplicate:" + id);
                    //}
                }
                sw.Stop();
                foreach (var item in set)
                {
                    Console.WriteLine("结果:" + item);
                }
                Console.WriteLine("时间:" + sw.ElapsedTicks);
                return;
    }
    
    
    算法:
    
     /// <summary>
        /// From: https://github.com/twitter/snowflake
        /// An object that generates IDs.
        /// This is broken into a separate class in case
        /// we ever want to support multiple worker threads
        /// per process
        /// </summary>
        public class IdWorker
        {
            private long workerId;
            private long datacenterId;
            private long sequence = 0L;
    
            private static long twepoch = 1288834974657L;
    
            private static long workerIdBits = 5L;
            private static long datacenterIdBits = 5L;
            private static long maxWorkerId = -1L ^ (-1L << (int)workerIdBits);
            private static long maxDatacenterId = -1L ^ (-1L << (int)datacenterIdBits);
            private static long sequenceBits = 12L;
    
            private long workerIdShift = sequenceBits;
            private long datacenterIdShift = sequenceBits + workerIdBits;
            private long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
            private long sequenceMask = -1L ^ (-1L << (int)sequenceBits);
    
            private long lastTimestamp = -1L;
            private static object syncRoot = new object();
    
            public IdWorker(long workerId, long datacenterId)
            {
    
                // sanity check for workerId
                if (workerId > maxWorkerId || workerId < 0)
                {
                    throw new ArgumentException(string.Format("worker Id can't be greater than %d or less than 0", maxWorkerId));
                }
                if (datacenterId > maxDatacenterId || datacenterId < 0)
                {
                    throw new ArgumentException(string.Format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
                }
                this.workerId = workerId;
                this.datacenterId = datacenterId;
            }
    
            public long nextId()
            {
                lock (syncRoot)
                {
                    long timestamp = timeGen();
    
                    if (timestamp < lastTimestamp)
                    {
                        throw new ApplicationException(string.Format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
                    }
    
                    if (lastTimestamp == timestamp)
                    {
                        sequence = (sequence + 1) & sequenceMask;
                        if (sequence == 0)
                        {
                            timestamp = tilNextMillis(lastTimestamp);
                        }
                    }
                    else
                    {
                        sequence = 0L;
                    }
    
                    lastTimestamp = timestamp;
    
                    return ((timestamp - twepoch) << (int)timestampLeftShift) | (datacenterId << (int)datacenterIdShift) | (workerId << (int)workerIdShift) | sequence;
                }
            }
    
            protected long tilNextMillis(long lastTimestamp)
            {
                long timestamp = timeGen();
                while (timestamp <= lastTimestamp)
                {
                    timestamp = timeGen();
                }
                return timestamp;
            }
    
            protected long timeGen()
            {
                return (long)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds;
            }
        }
  • 相关阅读:
    数据库分库分表
    工作笔记----数据库分表
    工作笔记----数据提取
    Runnable和Thread的应用场景
    LeetCode题目按公司分类
    spring boot Java配置搭建ssm (二)
    spring boot java配置搭建ssm 小案例(IDEA)
    spring boot xml配置搭建 ssm 小案例(IDEA)
    连接查询
    限定、模糊、排序、多表查询(3)
  • 原文地址:https://www.cnblogs.com/liyangLife/p/5754100.html
Copyright © 2011-2022 走看看