2012-03-11 109 views
7

我目前正在開發註冊系統原型。它非常簡單,基本上只是一個寫入MongoDB的.NET表單。針對數據庫條目的高效唯一密鑰生成

我卡與什麼是產生每個用戶的唯一ID /密鑰的有效方式。這些ID必須是人性化的,例如7個字符長的字母數字字符串,例如A1B2C3X。

我到目前爲止看到只使用一個簡單的函數來生成一個隨機字符串,然後檢查數據庫,看看它是否是唯一的(如果不是重複,直到你找到一個獨一無二的)的解決方案。隨着數據庫條目數量的增長,這當然會越來越計算成本。

我的想法是預先計算的唯一ID設置和存儲在另一個數據庫。然後,當我需要向用戶數據庫中添加一個新條目時,我可以從我的id數據庫中「持續」彈出一個id,並知道它不存在於用戶數據庫中,而無需搜索它。

我確定有人必須做過這樣的事情。有沒有更好的辦法?我不知道我爲什麼這麼掙扎。非常感謝您的意見。

+2

由MongoDB驅動程序提供的ObjectId是否對您的用例太不友好? – 2012-03-11 12:39:21

+0

我正在建議@EkinKoc的建議(如果你有40個字符,那麼這就是要走的路)。但是,如果您只需要7個字符,那麼您所概述的方法應該比使用單獨的數據庫密鑰存儲區彈出值更便宜*,更簡單,並且更少出錯。在隨機的7個字符的字母數字字符串上碰撞的機率幾乎爲零。這是一個罕見的邊緣情況,你不應該優化。 (無論如何用戶創建是很少見的,數據庫唯一性檢查對於相對較少的進程來說足夠快)。 – 2012-03-11 12:42:37

+0

@ BenLee:碰撞的概率隨着比例的變化而變化:) – 2012-03-11 12:44:06

回答

11

生成應用程序中的一個隨機字符串和檢查,如果它獨特的是不是一個壞的解決方案。不要擔心它效率低下,這不是 - 也絕不會與其他方法相比較。它肯定會比運行db.user.count()或保留具有預先計算的ID的單獨表格更快。你只需要做對。

首先,創建新用戶的頻率如何?可能與其他事情不太經常比較,所以整個效率討論實際上是沒有意義的。其次,A-Z有7個字符,0-9的範圍是36^7或者大約780億。至少可以說,在你開始看到碰撞之前還需要一段時間。

如果你只是像這樣做,它不會產生任何性能損失,除非有一個碰撞(這是非常不可能的):

  • 生成一個唯一的用戶ID
  • 插入用戶對象,使用用戶ID爲_id
  • 檢查重複鍵錯誤的值(如何做到這一點取決於語言和驅動程序,但可能涉及運行​​命令)。
  • 在重複鍵錯誤從頭再來通過生成新的用戶ID

這樣只會出現在碰撞的情況下,額外的工作(我真的,真的想強調的是多麼的不可能會是)。

還有另一種生成唯一用戶標識的方法:取當前的UNIX時間戳(第二個),追加主機名和進程標識的散列,最後是計數器的當前值。實際上,Mongo的ObjectId是如何生成的,並且確保您可以每個進程每秒生成多個對象,作爲您計數器的最大值(在Mongo中爲3個字節,即1600萬)。請參閱ObjectId上的文檔,如果您對這些細節感興趣:http://www.mongodb.org/display/DOCS/Object+IDs

它具有您的用戶ID自然按照創建順序排序的屬性,但它的長度爲12個字節,比7個字符長一些,不幸。您可以使用相同的方法並跳過主機名/ pid,並將計數器(如果您願意,也可以是一個隨機數)縮短爲兩個字節,那麼您將減少到6個字節,這可能會被壓縮到大約9字母AZ,0-9。

+0

感謝您的詳細解答。你的解決方案聽起來是最簡單的。現在插入使用_id然後檢查一個重複鍵錯誤,而不是手動檢查collison(在應用程序中),然後插入它是有意義的。我認爲這種微妙的差異是讓我對解決方案的效率感到擔憂,因爲只要你做得對,你正確地指出這是不合理的。再次感謝。 – 2012-03-11 14:28:29