我目前正在开展一个项目,在该项目中,只能向注册用户访问API。 API本身已经完成并按预期工作。限制对API的访问也相当简单。但是,我的问题(或者问题是)如何确保注册,验证和/或丢失和找到过程的数据库交互效率。
以下是目前发生的一个例子:
以下是数据库结构的示例: http://s13.postimage.org/h8ao5oo2v/dbstructure.png
正如您可能想象的那样,在此过程中的每个特定步骤后面都会有很多数据库交互。我想知道效率的一个步骤是检查某些项目的唯一性。显然,我们不希望任何重复的API密钥浮动,我们也不希望任何重复的电子邮件验证哈希值。
所以,我编写了一个简单的死函数,在将数据库插入数据库之前检查数据库。然而,这个项目的规模比我以前任何时候都要大几百倍。我之前已经建立并维护了为500到1,000名用户提供服务的项目......但是这个项目估计每天至少为50,000名用户提供服务。我很高兴我终于找到了一个大型项目,但在它的规模上变得越来越沮丧。
无论如何,这里是我写的与数据库交互的函数,用于在存储项目之前检查项目的唯一性。
function isUnique($table, $col, $data) {
mysql_connect("localhost", "root", "") or die(mysql_error());
mysql_select_db("api") or die(mysql_error());
$check = mysql_query("SELECT ".$col." FROM ".$table." WHERE ".$col."='".$data."'");
$match = mysql_num_rows($check);
if($match < 1) {
return true;
}
return false;
mysql_close('localhost');
}
此函数与另一个函数结合使用,该函数仅生成电子邮件验证哈希的随机40位数字0-9,a-z和A-Z字符串以及API密钥本身。 (以下功能)
function makeRandom($length = 40) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$randomString = '';
for($i = 0; $i < $length; $i++) {
$randomString .= $characters[mt_rand(0, strlen($characters) - 1)];
}
return $randomString;
}
然后,这两个功能的组合用于与API密钥发布相关的3个不同页面:第1页用于注册/请求,第2页用于验证电子邮件,第3页用于丢失密钥或未接收的电子邮件。现在,它在实践中:
$hash = makeRandom();
$unique = isUnique('users', 'hash', $hash);
if($unique == false) {
while($unique == false) {
$hash = makeRandom();
$unique = isUnique('users', 'hash', $hash);
}
}
else {
$searchactive = mysql_query("SELECT email, active FROM users WHERE email='".$email."' AND active='1'") or die(mysql_error());
$matchactive = mysql_num_rows($searchactive);
$searchinactive = mysql_query("SELECT email, active FROM users WHERE email='".$email."' AND active='0'") or die(mysql_error());
$matchinactive = mysql_num_rows($searchinactive);
if($matchactive > 0) {
$hash = mysql_query("SELECT hash FROM users WHERE email='".$email."' AND active='1'") or die(mysql_error());
$hash = mysql_fetch_assoc($hash);
$hash = $hash['hash'];
$msg = 'The email address you entered is already associated with an active API key. <a href="lost.php?email='.$email.'&hash='.$hash.'&active=1">[Recover Lost API Key]</a>';
}
elseif($matchinactive > 0) {
$hash = mysql_query("SELECT hash FROM users WHERE email='".$email."' AND active='0'") or die(mysql_error());
$hash = mysql_fetch_assoc($hash);
$hash = $hash['hash'];
$msg = 'The email address you entered is already pending verification. <a href="lost.php?email='.$email.'&hash='.$hash.'&active=0">[Resend Verification Email]</a>';
}
}
我的主要问题是:有了这么多查询,只是针对这样一个(看似简单的)简单函数,这会产生比解决的问题更多的问题吗?出于显而易见的原因,我确实需要确保没有任何重复的验证哈希值或API密钥。但是,估计有5万人使用此功能,由于SQL查询的数量,这是否会使服务器陷入困境?主要问题是由于while()循环用于在插入之前检查生成内容的唯一性。
我知道这不是幕后发生的事情的完整画面,但它确实提供了其余页面如何工作的线索。如果需要有关整个过程的更多信息,我将很乐意发布它。
感谢您提供的任何见解!
答案 0 :(得分:2)
解决这个问题的一种方法是不检查重复项,但只是确保它们从未发生过。因此,只需为您的用户表版本添加(为版本添加一个字段)。这只是一个int,它会在用户的行被更改时随时前进。
然后,当您生成随机密钥时,在存储密钥之前将user_id和user_version附加到其中。
示例:
11ap0w9jfoaiwej203989wesef
第一个是user_id,第二个是用户版本。
然后,即使在两次生成大密钥的统计上很小的可能性,它也将始终是唯一的,因为您的用户ID将是唯一的。
答案 1 :(得分:1)
我会考虑使用UUID而不是滚动自己的随机字符串。出于所有实际目的,这将是一个独特的价值。
http://dev.mysql.com/doc/refman/5.5/en/miscellaneous-functions.html#function_uuid