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
* Является ли GUID уникальным в 100% случаев? [StackOverflow]
Проблема с вашим GUID -> преобразование символов; в то время как ваш GUID является статистически уникальным, взяв любое подмножество, вы уменьшаете случайность и увеличиваете вероятность столкновений. Вы, конечно, не хотите создавать неуникальные 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 захватывает блок. псевдо-c # -код выглядит следующим образом.
-- 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;
}
}
Идея в том, что вы резервируете достаточно ключей, чтобы ваш код не попадал в базу данных часто, поскольку получение диапазона ключей - дорогостоящая операция. Вам необходимо иметь представление о количестве ключей, которое необходимо зарезервировать, чтобы сбалансировать потерю ключей (перезапуск приложения) и слишком быстрое исчерпание ключей и возврат к базе данных. Эта простая реализация не может повторно использовать потерянные ключи.
Поскольку в этой реализации используются база данных и транзакции, приложения могут работать одновременно, и все они генерируют уникальные ключи без необходимости часто обращаться к базе данных.
Обратите внимание, что вышеприведенное в общих чертах основано на key table
, стр. 222 из Образцы архитектуры корпоративных приложений (Fowler) . Этот метод обычно используется для генерации первичных ключей без использования столбца идентификаторов базы данных, но вы можете увидеть, как его можно адаптировать для ваших целей.