全局唯一ID

1. 订单号

订单号在业务系统中必不可取,往往需要具备:

1. 全局唯一  2. 方便传播 (因为往往需要根据订单号来查问题)

那么其关键怎么来保证 订单号的全局唯一呢 ? 本文只记录工作中见识到的线上运行方案。

2. 全局唯一ID

1. 利用db的方式 

该方式需要DBA提前生成好一批订单号,然后将订单号分发给各个业务线,各个业务线有专门的 orderiddb 来存储这些订单号

这样业务线只需要取这些订单号即可,怎么保证在获取的时候 不会重复获取到同一个订单号呢?  需要设计3张表 ,具体方案如下

Table: cglobalunifiedorderid (种子-订单表)

Field Type Comment
SeedID bigint(20) 种子ID(主键)
OrderID bigint(20) 订单号
ChannelType varchar(10)  渠道
SubType varchar(10)  子类型
DataChange_LastTime datetime 修改

Table : orderidseed (种子表)

Field Type Comment
SeedID bigint(20) 种子ID(主键)
DataChange_LastTime datetime 修改

Table: cunifiedorderhistory (历史订单ID表)

Field Type Comment
OrderID bigint(20) 订单号
DataChange_LastTime datetime 修改时间

其中 种子订单表 的orderid 表存储DBA分发的订单号

取订单号CODE如下:

       private static object lockGenerateOrderID = new object();
        /// <summary>
        /// 生成订单号
        /// </summary>
        /// <returns></returns>
        public long GenerateOrderID()
        {
            long orderID = 0;
            long seedId = 0;

            lock (lockGenerateOrderID)
            {
                seedId = GenerateOrderIdSeed();
                if (seedId <= 0)
                {
                    LogHelper.LogSOAInfo("GenerateOrderID", "未生成OrderIdSeed");
                    return 0;
                }

                orderID = QueryOrderId(seedId);
                if (orderID > 0)
                {
                    InsertOrderIdHistory(orderID);
                }
                else
                {
                    LogHelper.LogSOAInfo("GenerateOrderID", string.Format("根据OrderIdSeed:{0} 未获取到OrderID", seedId));
                }
            }

            return orderID;
        }

        private long GenerateOrderIdSeed()
        {
            var result = baseDao_W.ExecScalar("INSERT INTO orderidseed(DataChange_LastTime) VALUES(NOW());SELECT LAST_INSERT_ID();");
            if (result == null)
                return 0;

            return TypeUtil.ToInt64(result);
        }

        private void InsertOrderIdHistory(long orderId)
        {
            string sql = "INSERT INTO cunifiedorderhistory (OrderID)VALUES(@orderId)";
            StatementParameterCollection para = new StatementParameterCollection();
            para.AddInParameter("@orderId", DbType.Int64, orderId);
            baseDao_W.ExecNonQuery(sql, para);
        }

        private long QueryOrderId(long seedId)
        {
            string sql = "SELECT OrderID FROM cglobalunifiedorderid WHERE SeedID=@seedId";
            StatementParameterCollection para = new StatementParameterCollection();
            para.AddInParameter("@seedId", DbType.Int64, seedId);

            DataTable dt = baseDao_W.SelectDataTable(sql, para);

            if (dt == null || dt.Rows == null || dt.Rows.Count == 0)
                return 0;

            return TypeUtil.ToInt64(dt.Rows[0]["OrderID"]);
        }

当然分布式系统下,业内还有其他方案来生成全局唯一ID,以后研究的时候会在做记录。

 

posted @ 2018-07-28 23:11  六度僧人  阅读(184)  评论(0编辑  收藏  举报