以下是要求:
必须是字母数字,8-10个字符,以便用户友好.这些将作为唯一键存储在数据库中.我使用Guids作为主键,因此使用GUID生成这些唯一ID的选项将更可取.
我正在考虑一个base-n转换器的线路,它接受一个Guid并转换为一个8字符的唯一字符串.
简短,轻量级算法是首选,因为它会经常被调用.
8 characters - perfectly random - 36^8 = 2,821,109,907,456 combinations 10 characters - perfectly random - 36^10 = 3,656,158,440,062,976 combinations GUID's - statistically unique* - 2^128 = 340,000,000,000,000,000,000,000,000,000,000,000,000 combinations
*100%的GUID是唯一的吗?[堆栈溢出]
您的GUID问题 - >字符转换; 虽然您的GUID在统计上是唯一的,但通过采用任何子集,您可以减少随机性并增加碰撞机会.你当然不想创造非unqiue SKU.
解决方案1:
使用与对象和业务规则相关的数据创建SKU.
即,可能存在一个小的属性组合,使对象成为唯一(自然键).组合自然键的元素,对其进行编码和压缩以创建SKU.通常您只需要一个日期时间字段(即CreationDate)和一些其他属性来实现此目的.你可能在sku创作中有很多漏洞,但sku与你的用户更相关.
假设:
Wholesaler, product name, product version, sku Amazon, IPod Nano, 2.2, AMIPDNN22 BestBuy, Vaio, 3.2, BEVAIO32
解决方案2:
一种方法,它保留一系列数字,然后继续按顺序释放它们,并且永远不会返回相同的数字两次.您仍然可以在该范围内找到洞.虽然你不需要生成足够的sku来解决问题,但确保你的要求允许这样做.
实现是key
在具有计数器的数据库中具有表.计数器在事务中递增.重要的一点是,软件中的方法不是递增1,而是抓取一个块.pseudo-c#-code如下.
-- what the key table may look like CREATE TABLE Keys(Name VARCHAR(10) primary key, NextID INT) INSERT INTO Keys Values('sku',1) // some elements of the class public static SkuKeyGenerator { private static syncObject = new object(); private static int nextID = 0; private static int maxID = 0; private const int amountToReserve = 100; public static int NextKey() { lock( syncObject ) { if( nextID == maxID ) { ReserveIds(); } return nextID++; } } private static void ReserveIds() { // pseudocode - in reality I'd do this with a stored procedure inside a transaction, // We reserve some predefined number of keys from Keys where Name = 'sku' // need to run the select and update in the same transaction because this isn't the only // method that can use this table. using( Transaction trans = new Transaction() ) // pseudocode. { int currentTableValue = db.Execute(trans, "SELECT NextID FROM Keys WHERE Name = 'sku'"); int newMaxID = currentTableValue + amountToReserve; db.Execute(trans, "UPDATE Keys SET NextID = @1 WHERE Name = 'sku'", newMaxID); trans.Commit(); nextID = currentTableValue; maxID = newMaxID; } }
这里的想法是你保留足够的密钥,以便你的代码不经常进入数据库,因为获取密钥范围是一项昂贵的操作.您需要很好地了解需要保留的密钥数量,以便平衡密钥丢失(应用程序重新启动)与过快地耗尽密钥并返回数据库.这个简单的实现无法重用丢失的密钥.
因为此实现依赖于数据库和事务,所以可以使应用程序同时运行,并且所有应用程序都生成唯一键,而无需经常访问数据库.
请注意,上面的内容基于企业应用程序架构模式(Fowler)的key table
第222页.该方法通常用于生成主键而无需数据库标识列,但您可以看到它如何适应您的目的.
您可以考虑基数36.因为它可以做字母和数字.考虑从你的集合中删除I(眼睛)和O(哦),这样它们就不会与1(一)和0(零)混淆.有些人可能会抱怨2和Z.