2 回答
TA贡献1865条经验 获得超7个赞
好吧,我建议使用 LCG,Linear Congruential Generator。它有非常好的属性——给定正确的常量集(赫尔-多贝尔定理)输出唯一地覆盖所有 2 32空间(或 64 位空间,但据我记得 PHP 只有 32 位整数)。基本上它是从 [0...2 32 ) 间隔到另一个 [0...2 32 ) 间隔的一对一映射器。它可以以两种方式使用
一、ID next = LCG(ID prev ),就像典型的随机数生成器一样。或者只是从线性递增计数器 ID next = LCG(1, 2, ...) 中输入它。您可以将整数转换为 8 个符号 base-16 字符串,应该足够好了。
没有 PHP 代码,有一个 python 代码
import numpy as np
class LCG:
UZERO: np.uint32 = np.uint32(0)
UONE : np.uint32 = np.uint32(1)
def __init__(self, seed: np.uint32, a: np.uint32, c: np.uint32) -> None:
self._seed: np.uint32 = np.uint32(seed)
self._a : np.uint32 = np.uint32(a)
self._c : np.uint32 = np.uint32(c)
def next(self) -> np.uint32:
self._seed = self._a * self._seed + self._c
return self._seed
def seed(self) -> np.uint32:
return self._seed
def set_seed(self, seed: np.uint32) -> np.uint32:
self._seed = seed
def skip(self, ns: np.int32) -> None:
"""
Signed argument - skip forward as well as backward
The algorithm here to determine the parameters used to skip ahead is
described in the paper F. Brown, "Random Number Generation with Arbitrary Stride,"
Trans. Am. Nucl. Soc. (Nov. 1994). This algorithm is able to skip ahead in
O(log2(N)) operations instead of O(N). It computes parameters
A and C which can then be used to find x_N = A*x_0 + C mod 2^M.
"""
nskip: np.uint32 = np.uint32(ns)
a: np.uint32 = self._a
c: np.uint32 = self._c
a_next: np.uint32 = LCG.UONE
c_next: np.uint32 = LCG.UZERO
while nskip > LCG.UZERO:
if (nskip & LCG.UONE) != LCG.UZERO:
a_next = a_next * a
c_next = c_next * a + c
c = (a + LCG.UONE) * c
a = a * a
nskip = nskip >> LCG.UONE
self._seed = a_next * self._seed + c_next
#%%
np.seterr(over='ignore')
a = np.uint32(1664525)
c = np.uint32(1013904223)
seed = np.uint32(1)
rng = LCG(seed, a, c)
print(rng.next())
print(rng.next())
print(rng.next())
TA贡献1820条经验 获得超9个赞
我写的一篇文章包含有关唯一随机标识符的建议。从您的问题来看,您似乎面临以下困境:生成随机唯一标识符——
足够长以至于难以猜测,但是
足够短,便于最终用户输入。
那篇文章中的建议解释了如何生成唯一的随机 ID(128 位或更长,使用加密 RNG,例如random_bytes
在bin2hex
PHP 中)。但出于您的目的,生成的 ID 可能太长而不适合。有一些方法可以处理如此长的 ID,包括——
将 ID 划分为可记忆的块(例如:“374528294473”变为“374-538-294-473”),
将 ID 转换为一系列容易记住的单词(如比特币的 BIP39),或
在 ID 的末尾添加一个所谓的“校验和数字”以防止输入错误。
在决定使用比该文章中的建议更短的 ID 之前,您应该尝试 (1) 或 (2)。
此外,您的应用程序通常必须根据已生成的 ID 数据库检查 ID 的唯一性;但是,这种唯一性检查可能会或可能不会成为您的应用程序的性能瓶颈,唯一的方法是尝试并查看。或者,您可以将 ID 表的记录号(对于每条记录应该是唯一的)包含在 ID 本身中。
如果订单 ID 是唯一授予访问该订单信息的权限,则也可能存在严重的安全问题。理想情况下,应该有其他形式的授权,例如只允许登录用户或某些登录用户访问与订单 ID 关联的订单信息。另请参阅此问题。
- 2 回答
- 0 关注
- 185 浏览
添加回答
举报