生成唯一的帐号-递归调用
嗨,我需要生成9位数字的唯一帐号。这是我的伪代码:
function generateAccNo() generate an account number between 100,000,000 and 999,999,999 if the account number already exists in the DB call generateAccNo() /* recursive call */ else return new accout number end if end function
该函数似乎运行良好,但是我对递归调用有点担心。
这会导致任何内存泄漏(Apache 5下的PHP 5)吗?
这是解决这个问题的可接受方法吗?
感谢输入。
解决方案
我们意识到这很可能导致堆栈溢出,对吗?随着客户数量的增加,找不到可接受的帐号的可能性也会增加。
另外,为什么我们不能只做连续的帐号,而每次只增加一个呢?使用这种方法,我们只需要读取数据库中当前的最大id并对其进行递增即可。
抱歉,这么钝,但是解决方案是解决问题的糟糕方法。它会使用大量的内存(因为堆栈可能会无限增长),并且它将对数据库进行大量昂贵的调用。
我们应该真正考虑其他方法:
我强烈建议我们在每次创建客户时仅增加客户编号。实际上,如果我们正确设置了数据库(在id列上具有自动递增的功能),则甚至不必设置id。每当我们插入新客户时,系统都会为我们设置ID。
我们无需在此处使用递归。一个简单的循环将同样快,并且消耗更少的堆栈空间。
我们可以将其放入while循环中:
function generateAccNo() while (true) { generate an account number between 100,000,000 and 999,999,999 if the account number already exists in the DB /* do nothing */ else return new accout number end if } end function
看起来不错,但是我认为我们需要某种死亡条件,在放弃之前,我们要让它运行多少次?
我知道在庞大的数字范围内这似乎不太可能,但是可能会出问题,只是使我们退回到上一个呼叫,该呼叫将再次被称为广告博物馆。
此处无需使用递归调用。在功能测试中运行一个简单的while循环,以不存在条件为条件,例如
function generateAccNo() generate an account number between 100,000,000 and 999,999,999 while ( the account number already exists in the DB ) { generate new account number; } return new account number end function
但是,如果此代码用于玩具以外的其他任何事物,则随机生成和测试是生成唯一帐号的次佳方法。
为什么不:
lock_db do account_num <= generate number while account_num in db put row with account_num in db unlock_db
数据库为什么不处理呢?在SQL Server中,我们可以只具有一个以100000000开始的标识列。或者我们可以在拥有的任何数据库中使用sql。只需获得最大ID加1.
顺序生成帐号是一种安全风险,我们应该找到其他一些算法来实现。
或者,我们可以维护一个单独的表,其中包含一个已生成的缓冲区(称为唯一帐号)。该表应具有一个自动递增的整数ID。当我们需要一个帐号时,只需在缓冲区中检索索引最低的记录并将其从该表中删除即可。有一些定期运行的过程可以补充缓冲区并确保其容量>>正常使用。优点是最终用户花费在创建帐号上的时间量基本上是恒定的。
另外,我应该注意的是处理开销或者递归或者迭代的风险,真正的问题是确定性和重复数据库查询的开销。我喜欢TheZenker的随机+顺序解决方案。保证生成唯一的ID,而不会增加不必要的开销。
我真的不认为这归结于递归与循环,随着数据集的增长以及随机数生成未正确实现,两者都容易出现问题。我想到两个主意:
。图形用户界面
如果需要尽可能少的努力才能获得真正唯一的ID,请考虑使用GUID,如果没有在代码中创建一个ID,则数据库很可能会在插入时为我们分配。尽管不是很友好,但可以保证它是唯一的。但是,与插入时数据库生成的顺序AccountRecordId结合使用时,我们将获得可靠的组合
。复合键:随机+顺序
一种解决所有需求的方法,尽管从表面上看有点麻烦,但它是使用5位数(或者更多)的顺序db密钥创建一个复合帐号,然后再使用5位数的随机性来创建。如果随机数重复,则没关系,因为顺序ID可以保证整个帐号的唯一性