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,以后研究的时候会在做记录。