Ответ 1
Вы можете рассмотреть base 36. в том, что он может делать буквы и цифры. Попробуйте удалить я (eye) и O (Oh) из вашего набора, чтобы они не смешивались с 1 (одним) и 0 (ноль). Некоторые люди могут также жаловаться на 2 и Z.
Вот требования:
Должно быть буквенно-цифровое, 8-10 символов, чтобы оно было удобным для пользователя. Они будут храниться как уникальные ключи в базе данных. Я использую гиды в качестве первичных ключей, поэтому предпочтительнее использовать GUID для генерации этих уникальных идентификаторов.
Я думаю о строках базового-n конвертера, который берет Guid и преобразует в уникальную строку с 8 символами.
Короткий, легкий алгоритм предпочтительнее, поскольку его можно было бы назвать довольно часто.
Вы можете рассмотреть base 36. в том, что он может делать буквы и цифры. Попробуйте удалить я (eye) и O (Oh) из вашего набора, чтобы они не смешивались с 1 (одним) и 0 (ноль). Некоторые люди могут также жаловаться на 2 и Z.
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 - statistically unique* - 2^128 = 340,000,000,000,000,000,000,000,000,000,000,000,000 combinations
* fooobar.com/questions/3947/...
Проблема с преобразованием символов 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-С# -код выглядит следующим образом.
-- 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). Этот метод обычно используется для генерации первичных ключей без необходимости в столбце идентификации базы данных, но вы можете видеть, как он может быть адаптирован для вашей цели.
Если вы ищете "удобную для пользователя", вы можете попробовать использовать целые слова, а не просто делать его коротким/буквенно-числовым, таким образом, что-то вроде:
words = [s.strip().lower() for s in open('/usr/share/dict/canadian-english') if "'" not in s]
mod = len(words)
def main(script, guid):
guid = hash(guid)
print "+".join(words[(guid ** e) % mod] for e in (53, 61, 71))
if __name__ == "__main__":
import sys
main(*sys.argv)
Что производит вывод, например:
oranjestad+compressing+wellspring
padlock+discommoded+blazons
pt+olenek+renews
Это забавно. В противном случае, просто взяв первые 8-10 символов хэша guid или sha1/md5 руководства, вероятно, ваш лучший выбор.
Простейшая вещь, которая могла бы работать, - это счетчик, который увеличивается каждый раз, когда требуется значение. Восемь цифр (с левым-ноль-дополнением) дают вам 100 миллионов возможных значений 00000000 через 99999999 (хотя вы можете вставлять пробелы или дефисы для удобства чтения, как в 000-000-00).
Если вам понадобится более 100 миллионов значений, вы можете либо увеличить длину, либо использовать буквы в альтернативных позициях. Использование A0A0A0A0 через Z9Z9Z9Z9 дает вам более четырех с половиной миллиардов возможных значений (4,569,760,000). Это тривиальный бит кода, который принимает длинное целое число и создает такую кодировку (mod 10 для самой правой цифры, div на 10, затем mod 26 для самой правой буквы и т.д.). Если у вас есть память для записи, самый быстрый способ состоит в том, чтобы преобразовать счетчик в массив mod 260 и использовать каждое значение mod 260 как индекс в массив двухсимвольных строк ( "A0", "A1", "A2" и т.д. через "A9", B0 "," B1 "и т.д. Через" Z9 ").
Проблема с базой 36 (упомянутая в другом ответе) состоит в том, что вам нужно не только беспокоиться о путанице читателя с подобными символами (один против I, ноль против O, два против Z, пять против S), но также о комбинациях смежных букв, которые могут восприниматься читателями как орфографические отвратительные или непристойные слова или аббревиатуры.
Вы можете попробовать алгоритм хеширования CRC32. CRC32 генерирует 8-значную строку.