如何生成8个字符的唯一字符串,而不检查它是否存在于数据库中

时间:2016-02-04 06:10:24

标签: mysql ruby-on-rails algorithm unique uniqueidentifier

我想每天生成100万个二维码。每个qr代码应该有random unique value.以实现唯一性我有两个选项,如下所示

1)第一个选项是生成8个字符的字母数字随机字符串,并检查它是否存在于数据库中。如果不存在,则存储在数据库中,如果存在,则重试增益。

这种方法的问题是生成100万个唯一的字母数字字符串需要大约45分钟,因为我们每次都必须检查数据库中是否存在生成的字母数字字符串。

2)第二个选项是通过在时间(小时+分钟+秒+日期+月+年)附加6个字符的字母数字字符串来生成唯一令牌。使用此选项,我可以在5分钟内生成100万个唯一的字母数字字符串。

我正在使用第二个选项,但此选项的问题是由此生成的字母数字字符串长度为15个字符。我想生成只有8个字符长的字母数字字符串。如果我使用第二个选项,那么时间戳本身需要8个字符,字符串变得容易猜到。

我想知道如何生成8个字符的随机和唯一的字母数字字符串,而不检查它是否存在于数据库中。

4 个答案:

答案 0 :(得分:0)

新计划。

每天,取数字000000..999999,随机播放,base64编码(3个字符)。

将服务开始后的天数作为六位数字,base64编码(3个字符)。好一百万天。

请注意,这些数字是唯一且“随机”的,但绝对不是加密安全的。

编辑一些伪代码:

int a[1000000];
int daysWeveBeenDoingThis;

for i from 0 to 999999 {
    a[i] = i
}
ShuffleArray(a);

function getNthTokenToday ( int n ) {
    String s = '';
    long x =
        (a[n] << 16L) + daysWeveBeenDoingThis);
    for c from 0 to 5 {
        v = (x >> (c*6)) & 63;
        b = 'a-zA-Z0-9/.'[v];
        s.append(b)(
    }
    return s;
}

答案 1 :(得分:0)

使用set结构就足够了

def random_str(n):
    base = 'abcefghijklmnopqrstuvwxzy0123456789'
    return ''.join([base[ord(i) % len(base)] for i in os.urandom(n)])

s = set()
SIZE = 1000000
while len(s) < SIZE:
    s.add(random_str(5))

而且,大约需要5秒钟。

抱歉,我每天都错过了。将8个字符拆分为两个部分:第一部分(3个字符)表示每天或其他条件,可以将其存储在Mysql中并在生成一次或使用自1970年以来的日期之前进行查询并将其更改为基于36的数字。秒数部分使用上面的代码5个字符生成唯一键。

答案 2 :(得分:0)

您可以使用对称加密(例如AES)来创建唯一ID。

首先,创建一个唯一的密钥。

其次,初始化一个计数器。

对于您要生成的每个新代码,使用加密密钥加密当前计数器值并使用它。并递增计数器。

PS:你想要使用字母数字输出只是一个小小的奇怪之处。因此,使用32位密钥,您将获得32位输出。现在,将其转换为8字节的字母数字输出。

答案 3 :(得分:0)

试试这个......

token = SecureRandom.urlsafe_base64(6) # This will give you 8 char uniq string

希望这对你有用。