由于登陆需要读数据库,创建用户等一系列操作,非常耗时,为了保证登陆接口正常工作,在一些高并发场景下,登陆削峰非常重要,本文在基于redis这个高性能内存数据库的基础上,提供了一种登陆排队系统的设计思路。
千言万语,其实一张流程图就ok:
流程图很简单,但是看上去可能一脸蒙蔽,以下是解释:
1、是否繁忙
是否繁忙是基于服务器的性能的,因此排队系统第一步,得出自己的服务器的性能上限,根据服务器的内核数,使用的编程语言,以及业务逻辑,性能这个指标算起来很复杂。QPS这个参数可以比较直观的显示服务器的性能,假设经过测试登陆接口的QPS上限是1000,那么就把这个1000用作判断服务器繁忙的指标。
然后一个重要的地方是这个1000怎么用呢,用起来也很简单,使用时间戳为key,每次登陆使这个key的value+1,如果发现这个key的值已经超过1000,那么就可以判定此时登陆人数过多,服务器繁忙,需要排队,然后还需要一个定时脚本,每隔一段时间把之前没用的key删除。
2、是否有排队号
首先这个排队号不是凭空来的,它是按照规则生成的,redis的有序集合zrank命令,member是用户的id,score是登陆的时间戳(毫秒)。用户第一次登录时用zadd添加,然后通知用户排队,下次登陆用zrank命令来看用户是否有排队号,当然这里存在一个问题是有些用户登陆发现要排队,他直接撤退了,下次这个人不会再登陆了,这个时候有序集合就会多出一条无用数据,所以需要一个定时脚本,每隔一段时间把之前没用的member删除。
3、满足排队条件
之前2里面已经拿到了排队号,就是zrank的结果,拿这个结果与1000比,为什么是1000?请看1,小于1000说明满足排队条件,排队轮到这个人了,大于1000则不满足条件。
4、其他
返回需要排队,这有什么用呢?或者说怎么用呢?这个排队号返回给前端,前端就要做一些工作了,比如排队号返回2000,那么前端就要按照服务器的性能,在2000/1000 = 2s 后让用户再次登陆,换个说法就是让登陆按钮不可用2秒钟,如果返回3000那就不可用3秒钟。
总结:这算是工作中对redis的一个应用吧,可能存在一些小问题,但是思路是没问题的。