网站采用分布式部署,读写分离,且写入数据库服务器有多个,登陆注册服务器目前有一个,用户表暂时有10个,每张表预计存储2千万条。
请问:
一、用户注册的时候,怎么查询用户名是否已经存在?有什么好的高效的方案?
二、如何设计方案,把用户放到把用户存储到相应的表中?
三、用户登陆的时候,怎么知道用户在哪个表中?
问题比较棘手、紧急,希望大家能够帮忙邀请各路大神解答,谢谢了。
回复内容:
这个东西说起来简单实际操作起来复杂。建议看一下eventual consistency的Wiki页面。
如果确认10个表,N年都不会变,那太简单了。把用户名当成是36进制的数字(26个字母+10个数字),直接mod 10取余决定到哪个用户表读写。
但是你要先知道这么做的坑在哪里…具体去看eventual consistency吧…
这个问题就由我来终结吧。
一般情况下,用户登录使用的是用户名或者邮箱+密码的方式来请求登陆验证。
假设我们有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的数字。到这里,我们就解决了以下的三个问题:
一、用户注册的时候,怎么查询用户名是否已经存在?有什么好的高效的方案?
二、如何设计方案,把用户放到把用户存储到相应的表中?
三、用户登陆的时候,怎么知道用户在哪个表中?
show me code:
<code class="language-php"><span class="x">function get_user_table_name($username, $prefix = 'user_', $count = 10){</span>
<span class="x"> return $prefix . abs(crc32($username)) % $count;</span>
<span class="x">}</span>
<span class="x">var_dump(get_user_table_name('username1'));</span>
<span class="x">var_dump(get_user_table_name('nameuser2123'));</span>
<span class="x">var_dump(get_user_table_name('用户名12'));</span>
<span class="x">var_dump(get_user_table_name('逆天杀神'));</span>
<span class="x">/**</span>
<span class="x"> * dump:</span>
<span class="x"> * string(6) "user_2"</span>
<span class="x"> * string(6) "user_8"</span>
<span class="x"> * string(6) "user_5"</span>
<span class="x"> * string(6) "user_9"</span>
<span class="x"> */</span>
</code>
泻药,,,
===========
MD5 + hexdec ,结合以上回答,提示的已经够多了~
把用户名hash,再mod,就知道它该在哪个表里了。
然后判断用户名是否存在只需要查一次。
-------------------------------------------------------------------
这种二话不说就开始讽刺人的风气从哪里来的,好好回答个问题会死?
我已经把没用的答案点了反对+没有帮助
第一个问题,存储的时候用hash,这个就能快速找到。
第二个问题,建立索引解决。
第三个问题,使用索引查询,用户不需要知道访问哪个表,哪个文件系统。索引来搞定这个方面的事情。
这个量级没必要分表,memcached加个用户名的查询缓存就解决了。
如果非要分,先hash取模实现,后面顶不住再拆吧。
两亿条真的需要分表么???
仅性能角度考虑,如果用oracle,有asm,连分区都不用了吧。
哈哈,这个很简单呀!
第一个问题不说了,查重有很多办法,回答已经很多了,题主应该可以解决;
第二个问题,取每个用户名的首自母,把用户表拆分成26个(必须是十个表的话也没关系,大不了一个表存三个自母),相应的用户名放到相对应首字母的表中,这样做好处很多,在用户量很大的情况下基本保持每个用户表存储数量基本均衡,且不混乱,加快查询速度,减少冗余;
问题三:哈哈,通过问题二不是已经解决了问题三了吗?用户登陆时,找它对应的首自母表就好了。
…………………分隔线…………………………
总结:
通过用户名首字母拆分,直接解决问题二三,且对查询速度有大幅度提升,同时线性降低表冗余,而且也顺带解决了表均衡问题。
对问题一查重效率也很有帮助,直接查对应首自母的表,使总查询总量降为原来的1/26,如果再对每张表做一些优化的话,效率更会有大幅度提升。
哈哈,大概就是这样!
如果有想的不对的地方,欢迎指正,欢迎骚扰,欢迎私信…(๑•̀ㅂ•́) ✧
别过度设计了 你什么项目 能有2亿的注册用户量???
如果你撑死也不会超过几千万,就别整这么花哨。
1.判断重复,用cache exits 就行了 用户名直接做key
2.根据(注册)时间戳等信息生成分布式的唯一ID,hash取模去分表或者直接按时间的区间分表
最简单的是直接把用户名hash了去分表,方便第三步3分表查找。
3.查某一位用户的时候怎么去找那张表?那得看你根据什么条件去查找啦。用户名,简单。