Heim >Backend-Entwicklung >PHP-Tutorial >分布式网站,用户注册如何查询用户名唯一,且保证分表高效?

分布式网站,用户注册如何查询用户名唯一,且保证分表高效?

WBOY
WBOYOriginal
2016-06-17 08:32:372159Durchsuche

网站采用分布式部署,读写分离,且写入数据库服务器有多个,登陆注册服务器目前有一个,用户表暂时有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.查某一位用户的时候怎么去找那张表?那得看你根据什么条件去查找啦。用户名,简单。
Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn