双11订单号并发生成问题大讨论,欢迎发表

zhanglong_longlong 2016-11-11 03:08:05
我现在正在做一个项目的基础上,NET,与销售有关的东西。需要创建订单号?这是我的想法:
i)安全:我不想创造像1,2,3 ......行在int简单序列的ID,因为这似乎让我卖给我的客户有多少东西。
二)并行冲突:对于一些特殊的日子我们可能1秒的几个客户进来,如果我们的算法不好,也许是重复的订单号。直到现在我还用这样的事情(在伪码):
string GenerateCode()
{
Thread.Sleep(1);
return DateTime.Now.ToString("yyyyMMddHHmmssfffff");
}
为了避免重复生成的代码,我必须使用线程。睡眠(1)来延迟,以确保时间是唯一的。然而,我必须这样做吗?我认为这个解决方案只是为了避免重复,有没有其他的方法来避免使用“Thread.Sleep(1)”?
三)曾有一段时间我想使用GUID,但最好使用订单的字符个数(12 ~ 16位数)。
所以根据我上面的描述,我想没有一个能满足我的需要:
如果我需要一位12 ~ 16位数(纯数字)没有任何重复的......所以在伪码算法是什么?请解释如何和为什么这是更好?
谢谢!
...全文
801 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
yzf86211861 2016-11-15
  • 打赏
  • 举报
回复
引用 13 楼 shingoscar 的回复:
Nj+1 = (Nj + A) % M 如果A和M互质,这个公式就可以遍历0~M-1的所有数字
这个可以
xingyuan1hao 2016-11-14
  • 打赏
  • 举报
回复
Crazyrisk 2016-11-11
  • 打赏
  • 举报
回复
if (执行(select count(0) from _table where id=id) > 0)//重新调用 else { id = DateTime.Now.ToString("yyyyMMddHHmmssffffff"); }
Poopaye 2016-11-11
  • 打赏
  • 举报
回复
初始值和A很大的时候,也没人能猜测出订单有多少个 效率绝对高 至于并发,靠单个服务解决 或者多个服务采用不同的初始值,只要不冲突即可
Poopaye 2016-11-11
  • 打赏
  • 举报
回复
Nj+1 = (Nj + A) % M 如果A和M互质,这个公式就可以遍历0~M-1的所有数字
修改一下昵称 2016-11-11
  • 打赏
  • 举报
回复
可以考虑用数据库记录当前最大订单号,每次生成一个订单号就+1 使用时间戳来判断是否没有修改
zhanglong_longlong 2016-11-11
  • 打赏
  • 举报
回复
引用 10 楼 D56233577 的回复:
你可以使用代理键,比如GUID列作为主键。 订单号可以按你自己的规则储存,单号上可以设置一个唯一键。 你都5级了,写的代码和思路错误满天飞,真不可思议。
我已经说了啊,不喜欢这种方式,我之前想过DateTime.Now.ToString("yyyyMMddHHmmssfffff")+Hash(guid)但是有没有更好的做法
D56233577 2016-11-11
  • 打赏
  • 举报
回复
你可以使用代理键,比如GUID列作为主键。 订单号可以按你自己的规则储存,单号上可以设置一个唯一键。 你都5级了,写的代码和思路错误满天飞,真不可思议。
zrED159820 2016-11-11
  • 打赏
  • 举报
回复
可行 顶。。。
Crazyrisk 2016-11-11
  • 打赏
  • 举报
回复
我之前说那个方法效率相当高 而且主要程序不卡就不会重复
zhanglong_longlong 2016-11-11
  • 打赏
  • 举报
回复
引用 5 楼 Chinajiyong 的回复:
订单号就用ID自增列,再设置一个Guid的字段
我之前想过DateTime.Now.ToString("yyyyMMddHHmmssfffff")+Hash(guid)但是有没有更好的做法
  • 打赏
  • 举报
回复
public class IdWorker
    {
        public const long Twepoch = 1288834974657L;

        const int WorkerIdBits = 5;
        const int DatacenterIdBits = 5;
        const int SequenceBits = 12;
        const long MaxWorkerId = -1L ^ (-1L << WorkerIdBits);
        const long MaxDatacenterId = -1L ^ (-1L << DatacenterIdBits);

        private const int WorkerIdShift = SequenceBits;
        private const int DatacenterIdShift = SequenceBits + WorkerIdBits;
        public const int TimestampLeftShift = SequenceBits + WorkerIdBits + DatacenterIdBits;
        private const long SequenceMask = -1L ^ (-1L << SequenceBits);

        private long _sequence = 0L;
        private long _lastTimestamp = -1L;


        public IdWorker(long workerId, long datacenterId, long sequence = 0L)
        {
            WorkerId = workerId;
            DatacenterId = datacenterId;
            _sequence = sequence;

            // sanity check for workerId
            if (workerId > MaxWorkerId || workerId < 0)
            {
                throw new ArgumentException(String.Format("worker Id can't be greater than {0} or less than 0", MaxWorkerId));
            }

            if (datacenterId > MaxDatacenterId || datacenterId < 0)
            {
                throw new ArgumentException(String.Format("datacenter Id can't be greater than {0} or less than 0", MaxDatacenterId));
            }

            //log.info(
            //    String.Format("worker starting. timestamp left shift {0}, datacenter id bits {1}, worker id bits {2}, sequence bits {3}, workerid {4}",
            //                  TimestampLeftShift, DatacenterIdBits, WorkerIdBits, SequenceBits, workerId)
            //    );	
        }

        public long WorkerId { get; protected set; }
        public long DatacenterId { get; protected set; }

        public long Sequence
        {
            get { return _sequence; }
            internal set { _sequence = value; }
        }

        // def get_timestamp() = System.currentTimeMillis

        readonly object _lock = new Object();

        public virtual long NextId()
        {
            lock (_lock)
            {
                var timestamp = TimeGen();

                if (timestamp < _lastTimestamp)
                {
                    //exceptionCounter.incr(1);
                    //log.Error("clock is moving backwards.  Rejecting requests until %d.", _lastTimestamp);
                    throw new InvalidSystemClock(String.Format(
                        "Clock moved backwards.  Refusing to generate id for {0} milliseconds", _lastTimestamp - timestamp));
                }

                if (_lastTimestamp == timestamp)
                {
                    _sequence = (_sequence + 1) & SequenceMask;
                    if (_sequence == 0)
                    {
                        timestamp = TilNextMillis(_lastTimestamp);
                    }
                }
                else {
                    _sequence = 0;
                }

                _lastTimestamp = timestamp;
                var id = ((timestamp - Twepoch) << TimestampLeftShift) |
                         (DatacenterId << DatacenterIdShift) |
                         (WorkerId << WorkerIdShift) | _sequence;

                return id;
            }
        }

        protected virtual long TilNextMillis(long lastTimestamp)
        {
            var timestamp = TimeGen();
            while (timestamp <= lastTimestamp)
            {
                timestamp = TimeGen();
            }
            return timestamp;
        }

        protected virtual long TimeGen()
        {
            return System.CurrentTimeMillis();
        }
    }
git居然打不开,那直接将项目中的代码贴出来吧,不过不知道有没有更新
EnForGrass 2016-11-11
  • 打赏
  • 举报
回复
订单号就用ID自增列,再设置一个Guid的字段
zhanglong_longlong 2016-11-11
  • 打赏
  • 举报
回复
引用 2 楼 starfd 的回复:
直接用数据库的自增列……
但是我想生产的是有日期组合的订单号,如果你那种做法就需要根据日期字段+自增ID进行拼接了,不是很好的做法
  • 打赏
  • 举报
回复
至于你说的订单编号,你可以在git上查下IdWorker
  • 打赏
  • 举报
回复
直接用数据库的自增列……
Crazyrisk 2016-11-11
  • 打赏
  • 举报
回复
先判断当前生成的订单号是否存在,存在递归调用,不存在就插入

62,072

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

试试用AI创作助手写篇文章吧