分散式網站,用戶註冊如何查詢用戶名唯一,且保證分表高效?

網站採用分散式部署,讀寫分離,且寫入資料庫伺服器有多個,登陸註冊伺服器目前有一個,用戶表暫時有10個,每張表預計存儲2千萬條。

請問:

一、用戶註冊的時候,怎麼查詢用戶名是否已經存在?有什麼好的高效的方案?

二、如何設計方案,把用戶放到把用戶存儲到相應的表中?

三、用戶登陸的時候,怎麼知道用戶在哪個表中?

問題比較棘手、緊急,希望大家能夠幫忙邀請各路大神解答,謝謝了。


這個東西說起來簡單實際操作起來複雜。建議看一下eventual consistency的Wiki頁面。

如果確認10個表,N年都不會變,那太簡單了。把用戶名當成是36進位的數字(26個字母+10個數字),直接mod 10取余決定到哪個用戶表讀寫。

但是你要先知道這麼做的坑在哪裡…具體去看eventual consistency吧…


把用戶名hash,再mod,就知道它該在哪個表裡了。

然後判斷用戶名是否存在只需要查一次。

-------------------------------------------------------------------

這種二話不說就開始諷刺人的風氣從哪裡來的,好好回答個問題會死?

我已經把沒用的答案點了反對+沒有幫助


一般情況下,用戶登錄使用的是用戶名或者郵箱+密碼的方式來請求登陸驗證。

假設我們有10個表,user_0,user_1,user_2, ... user_9。

假設我們有幾個用戶,用戶名為username1,nameuser2123,用戶名12,逆天殺神。

當用戶「逆天殺神」請求登陸時,我們怎麼查找用戶名是否存在呢?我們先將用戶名做一個int hash,和md5類似,md5是將一段數據變成32位16進位字元串,而int hash是變成一個int值。int hash 見:Hash演算法 - hqd_acm的專欄

然後我們將這個int hash值求余,得到一個0-9的數字。到這裡,我們就解決了以下的三個問題:

一、用戶註冊的時候,怎麼查詢用戶名是否已經存在?有什麼好的高效的方案?
二、如何設計方案,把用戶放到把用戶存儲到相應的表中?
三、用戶登陸的時候,怎麼知道用戶在哪個表中?

example:

function get_user_table_name($username, $prefix = "user_", $count = 10){
return $prefix . abs(crc32($username)) % $count;
}

var_dump(get_user_table_name("username1"));
var_dump(get_user_table_name("nameuser2123"));
var_dump(get_user_table_name("用戶名12"));
var_dump(get_user_table_name("逆天殺神"));
/**
* dump:
* string(6) "user_2"
* string(6) "user_8"
* string(6) "user_5"
* string(6) "user_9"
*/

當然,這個方案是不完美的,因為每個用戶表的數據量是不絕對平均的。

有好的想法或者對本回答的意見歡迎在評論區回復。


瀉藥,,,

===========

MD5 + hexdec ,結合以上回答,提示的已經夠多了~


第一個問題,存儲的時候用hash,這個就能快速找到。

第二個問題,建立索引解決。

第三個問題,使用索引查詢,用戶不需要知道訪問哪個表,哪個文件系統。索引來搞定這個方面的事情。


我看有人回答,對用戶名採用hash,這種方法沒錯,但是實際業務場景是,一個用戶可能有多個用戶名,例如:手機號、郵箱、身份證作為登錄標識,好吧你這樣也可以做hash,但是登錄的時候,不可能用到一張表,哪第二張表怎麼關聯,用登錄標識顯然是不可行的。

------------------------

如果數據量不大話,建議做個全局表,存取登錄標識與用戶ID的關係,然後分庫的時候,以用戶ID為分庫鍵,保證同一用戶的業務數據在同一個庫中,以避免跨庫事務問題,採用一致性hash演算法,保證數據均勻分布。

------------------------

性能要求高的話,建議把登錄相關表做緩存,跟全局表一個概念,緩存失效在訪問全局表。


別過度設計了 你什麼項目 能有2億的註冊用戶量???

如果你撐死也不會超過幾千萬,就別整這麼花哨。

1.判斷重複,用cache exits 就行了 用戶名直接做key

2.根據(註冊)時間戳等信息生成分散式的唯一ID,hash取模去分表或者直接按時間的區間分表

最簡單的是直接把用戶名hash了去分表,方便第三步3分表查找。

3.查某一位用戶的時候怎麼去找那張表?那得看你根據什麼條件去查找啦。用戶名,簡單。


百度一下的事,基礎還是要過關吧

用戶賬號信息如何分表保存【洄溪吧】_百度貼吧


兩億條真的需要分表么???

僅性能角度考慮,如果用oracle,有asm,連分區都不用了吧。


哈哈,這個很簡單呀!

第一個問題不說了,查重有很多辦法,回答已經很多了,題主應該可以解決;

第二個問題,取每個用戶名的首自母,把用戶表拆分成26個(必須是十個表的話也沒關係,大不了一個表存三個自母),相應的用戶名放到相對應首字母的表中,這樣做好處很多,在用戶量很大的情況下基本保持每個用戶表存儲數量基本均衡,且不混亂,加快查詢速度,減少冗餘;

問題三:哈哈,通過問題二不是已經解決了問題三了嗎?用戶登陸時,找它對應的首自母表就好了。

…………………分隔線…………………………

總結:

通過用戶名首字母拆分,直接解決問題二三,且對查詢速度有大幅度提升,同時線性降低表冗餘,而且也順帶解決了表均衡問題。

對問題一查重效率也很有幫助,直接查對應首自母的表,使總查詢總量降為原來的1/26,如果再對每張表做一些優化的話,效率更會有大幅度提升。

哈哈,大概就是這樣!

如果有想的不對的地方,歡迎指正,歡迎騷擾,歡迎私信…(??????) ?


這個量級沒必要分表,memcached加個用戶名的查詢緩存就解決了。
如果非要分,先hash取模實現,後面頂不住再拆吧。


推薦閱讀:

TAG:資料庫 | PHP | 分散式 | 分表 | 讀寫分離 |