分散式網站,用戶註冊如何查詢用戶名唯一,且保證分表高效?
網站採用分散式部署,讀寫分離,且寫入資料庫伺服器有多個,登陸註冊伺服器目前有一個,用戶表暫時有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 就行了 用戶名直接做key2.根據(註冊)時間戳等信息生成分散式的唯一ID,hash取模去分表或者直接按時間的區間分表最簡單的是直接把用戶名hash了去分表,方便第三步3分表查找。3.查某一位用戶的時候怎麼去找那張表?那得看你根據什麼條件去查找啦。用戶名,簡單。
百度一下的事,基礎還是要過關吧
用戶賬號信息如何分表保存【洄溪吧】_百度貼吧
兩億條真的需要分表么???
僅性能角度考慮,如果用oracle,有asm,連分區都不用了吧。哈哈,這個很簡單呀!
第一個問題不說了,查重有很多辦法,回答已經很多了,題主應該可以解決;
第二個問題,取每個用戶名的首自母,把用戶表拆分成26個(必須是十個表的話也沒關係,大不了一個表存三個自母),相應的用戶名放到相對應首字母的表中,這樣做好處很多,在用戶量很大的情況下基本保持每個用戶表存儲數量基本均衡,且不混亂,加快查詢速度,減少冗餘;
問題三:哈哈,通過問題二不是已經解決了問題三了嗎?用戶登陸時,找它對應的首自母表就好了。
…………………分隔線…………………………
總結:
通過用戶名首字母拆分,直接解決問題二三,且對查詢速度有大幅度提升,同時線性降低表冗餘,而且也順帶解決了表均衡問題。對問題一查重效率也很有幫助,直接查對應首自母的表,使總查詢總量降為原來的1/26,如果再對每張表做一些優化的話,效率更會有大幅度提升。哈哈,大概就是這樣!如果有想的不對的地方,歡迎指正,歡迎騷擾,歡迎私信…(??????) ?這個量級沒必要分表,memcached加個用戶名的查詢緩存就解決了。
如果非要分,先hash取模實現,後面頂不住再拆吧。
推薦閱讀: