我目前正在从事一个项目,在这个项目中,对API的访问仅限于注册用户。API本身已经完成,并按预期工作。限制对API的访问也变得相当简单。然而,我的问题(或者说是问题)是如何确保数据库交互对于注册、验证和/或丢失和查找过程的效率。
下面是当前发生的情况的一个例子:
H 19如果用户忘记/丢失
H 210H 111,如果没有收到验证邮件,则可以再次发送H 212G 213。下面是数据库结构的一个示例:http://s13.postimage.org/h8ao5oo2v/dbstructure.png
正如您可能可以想象的那样,在这个过程中的每一个特定步骤都有大量的后台数据库交互。我想知道的一个步骤是检查某些项目的唯一性。显然,我们不希望任何重复的API键浮动,我们也不希望任何重复的电子邮件验证哈希。
因此,我编写了一个非常简单的函数,在将它们插入数据库之前检查数据库中的这些东西。然而,这个项目比我以前承担的任何项目都大数百倍。我建立并维护了为500-1000名用户服务的项目.但据估计,该项目每天至少为5万名用户提供服务。我非常高兴,我终于完成了一个大型项目,但它的规模变得越来越胆怯。
无论如何,这是我编写的函数,用于与数据库交互,在存储项目之前检查它们的唯一性。
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');
}此函数与另一个函数一起使用,该函数仅为电子邮件验证哈希和API密钥本身生成一个随机的40位字符串0-9、API和API。(职能如下)
function makeRandom($length = 40) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$randomString = '';
for($i = 0; $i < $length; $i++) {
$randomString .= $characters[mt_rand(0, strlen($characters) - 1)];
}
return $randomString;
}然后,将这两个功能组合在3个与API密钥颁发相关的不同页面中:第一页用于注册/请求,第二页用于电子邮件的验证,第三页用于查找丢失的密钥或未收到的电子邮件。现在,它正在实践中:
$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()循环用于在插入之前检查生成的内容的唯一性。
我知道这并不是幕后所发生的事情的全貌,但它确实给出了其他页面是如何工作的线索。如果需要更多关于整个过程的信息,我很乐意发布它。
感谢您所能提供的任何见解!
发布于 2012-05-03 20:20:05
解决这一问题的一种方法是不检查副本,而是确保它们从一开始就不会发生。因此,只需为您的用户表提供版本(为版本添加一个字段)。这将只是一个int,只要用户的行被更改,它就会前进。
然后,在生成随机密钥时,在存储密钥之前将user_id和user_version附加到其中。
示例:
11ap0w9jfoaiwej203989wesef
其中第一个是user_id,第二个是用户版本。
然后,即使在统计上一个大键被生成两次的可能性很小,它仍然是唯一的,因为您的用户id将是唯一的。
发布于 2012-05-03 20:28:54
我会考虑使用UUID,而不是滚动自己的随机字符串。就所有实际目的而言,这将是一个独特的价值。
http://dev.mysql.com/doc/refman/5.5/en/miscellaneous-functions.html#function_uuid
https://stackoverflow.com/questions/10438673
复制相似问题