首先要考虑到的问题:
- 是只输入密码错误就锁定还是账号和密码任意一个输入错误就锁定?
- 输错了以后为什么过几分钟后又可以输了?
- 到底是使用哪些技术栈实现的?
下面让我们带着这些问题逐个分析:
1.是只输入密码错误就锁定还是账号和密码任意一个输入错误就锁定?
锁定的是IP,不是输入的账号或密码(通俗的讲就是任意一个输入错误3次就会被锁定)。
2.输错了以后为什么过几分钟后又可以输了?
Redis中实现了过期策略,当key过期时锁定也就消失了。
3.到底是使用哪些技术栈实现的?
找到一套解决方案:SpringBoot+Redis+Lua脚本。
业务流程图:
然后根据技术栈我们画一个流程图来分析一下这个登录限制流程
-
从流程图上看,首先访问次数的统计与判断不是在登录逻辑执行后,而是执行前就加1了;
-
其次登录逻辑的成功与失败并不会影响到次数的统计;
-
最后还有一点流程图上没有体现出来,这个次数的统计是有过期时间的,当过期之后又可以重新登录了。
-
那为什么是Redis+Lua脚本呢?
-
Redis的选择不难看出,这个流程比较重要的是存在一个用来计数的变量,这个变量既要满足分布式读写需求,还要满足全局递增或递减的需求,那Redis的incr方法是最优选了。
那为什么需要Lua脚本呢?流程上在验证用户操作前有些操作,如图:
这里至少有3步Redis的操作,get、incr、expire,如果全放到应用里面来操作,有点慢且浪费资源。
Lua脚本的优点如下:
-
减少网络开销。 可以将多个请求通过脚本的形式一次发送,减少网络时延。
-
原子操作。 Redis会将整个脚本作为一个整体执行,中间不会被其他请求插入。因此在脚本运行过程中无需担心会出现竞态条件,无需使用事务。
-
复用。 客户端发送的脚本会永久存在redis中,这样其他客户端可以复用这一脚本,而不需要使用代码完成相同的逻辑。