【总结+面试考点1】用户名防重名设计

考点

关于用户名防重复的设计,是一类实际项目中非常 常见的问题,归属「防重」这一类问题,针对这个问题,如果你在简历中写了这个事情,那么在面试可能面试官就会和你谈 造火箭的,比如可能会问如下问题:

1、比如通过查询数据库判断重复,那高并发下怎么办?这样会出现重复
2、有人可能会说,我可以用唯一字段约束,这确实是最省事的,但是我们不应该把问题抛给数据库去处理,应该是业务层处理,而且用了唯一约束,其实会影响后续的拓展,毕竟改表操作是一个很危险的操作。
3、有人可能会说,我可以用 sychronized 加锁的,但是sychronized 只能锁单机,而且我们还得保证锁的力度尽量小。
4、好吧,我 用分布式锁吧,那用啥作为分布式锁?最简单的就是 redis,但是redis有很多抗,可能面试官还会让你手写一个。
5、好吧,用redis来分布式锁,那 key 应该是什么呢?怎么设置key才更加高效呢?
……
这些,都能 成为连环炮,当然,我们不求最优解,只求 思考过,给出面试官一个合理的答复。

解决思路参考

一般情况下,很多人会用直接去数据库查询是否有重名的用户,现在在高并发情况下是不可以的,所以解决方法一般如下几个:

1、直接用数据库的唯一字段来限制:这是一个很简单的方法,也是一个很粗暴的方法,但是这种事情不应该丢给数据库去处理,应该由业务层来处理,而且如果给了数据库处理,不便于日后的拓展,比如你日后想要弄分库分表,又或者说,突然你就允许昵称重复了,你总 不能去改表吧?

所以呢,我们不能通过唯一字段来限制。

2、通过加锁:还有一种比较简单的方法,就是加 sychronized 锁,不过改方法也不大行,一是 sychronized 锁的力度比较大,而且遇到分布式,也处理不了,只能处理单机。

说到分布式,我们就容易想到用分布式锁。

是的,我们得用分布式锁来解决,分布式锁可以用 redis,也可以用 zookeeper 这些,不过我们就说一说如何用 redis 吧,因为 redis 实现起来容易,但是 zookeeper 也要了解,这里我就不多说了,具体redis代码怎么实现分布式锁请看这篇:61. Redis实现分布式锁

下面我们说一说用 redis 实现时,需要注意以及可以优化的点。

第一个需要考虑的问题就是用 redis 实现时,关于 key 的设计,在我们平时的分布式锁时,key 肯定是固定一个值的,但是在防重名这种,如果你固定一个值的话,效率就会非常慢。

比如有 100 人来注册,这 100 人在注册时,名字都是不一样的,如果你是固定的 key,意味着这 100 人都得去等锁,相当于串行注册,显然这效率太低了。

所以呢,对于这种防重复名字的,我们可以用 用户标识+固定值来作为 key,这样只有名字相同时,才需要去等待锁,而用户名相同的概率其实很低的,所以呢,这种的话,效率就会非常搞,基本不需要等待。

不过这样也会导致一个问题 ,那就是内存在存在大量的 key,这其实也不难办,我们可以在注册成功后,把这个 Key 给删除了,删除就意味着释放锁了。

以上便是一个参考思路,大家还能把这个问题,当作是你在做项目遇到什么难点来处理,不过 你要把分布式相关的东西准备好,包括用 redis 实现分布式锁,有啥优缺点,zookeeper 又是可以如何实现,等等。

记住,做咱们这个项目,你一定要花时间去思考,否则项目做了没啥用,被问到还是不会哦。

发表评论

后才能评论