【精选】redis实现的登录排队(限流) |
您所在的位置:网站首页 › 英雄联盟排队机制 › 【精选】redis实现的登录排队(限流) |
游戏登录排队( 限流)
文章目录
游戏登录排队( 限流)前言为什么要排队(限流)限流算法固定窗口实现的登录限流流程图:代码实现生产环境下的限流组件参考
前言
能看到这篇帖子的兄弟,可能是想实现一个游戏登录排队的功能。游戏的登录排队机制,其实就是 服务的限流 、削峰机制,如果 你使用 “限流” 关键词可能会搜索到更多的相关资料。 为什么要排队(限流) 最近我司游戏要上线了,目前全平台总预约量有600多万。服务器目前的配额,压测目标是,允许250万玩家同时在线的情况下,服务依然稳定。但是游戏上线开服第一天,假设所有玩家(假设是压测的250万玩家)第一时间注册上线,那么带来的 DB写操作,将是噩梦。服务器本身可以支持250w玩家同时在线,但是db并不能满足250w玩家短时间的写操作。玩家注册操作的写db操作比较重。 所以就需要削峰、限流。也就是这里的登录排队。 假设数据库写操作最大支持 5000 次/秒,玩家注册时写 db 频率是 2 次/秒。那么 db能够承受的玩家登入速度 是 2500 人/秒。所以如果 一秒钟登录的用户超过2500人后,后来的用户登录就需要排队,至少要等到下一秒才能允许登录。 限流算法 固定窗口:滑动窗口:漏斗桶算法:令牌桶算法:固定窗口和滑动窗口都是计数法。 服务器架构图: 为了方便理解,这里先介绍一下我的项目简易架构图。 登录排队机制应该在哪一步? 在client->login 的过程中在 client -> gateway的过程中不忘初心:前面“为什么需要限流” 中说明了,是因为服务器db扛不住压力,所以排队操作一般会放在数据库操作之前。 这里我们采用了方案一, 在login服上进行排队。登录验证使用的HTTP协议。短链接的HTTP 会有一个麻烦,当玩家排队结束时(轮到玩家登录了),服务器不能够主动告诉客户端 “到你了,轮到你登录了”。所以服务器只能在每次客户端登录请求的回复中 带上 一个等待时间。告诉客户端还需要等多久。 客户端收到这个时间后,自己在等待时间结束后重试。 如果采用方案二,客户端与服务器是长链接,可以在客户端的排队等待时间结束后,主动告诉客户端。(TCP是全双工通信,双方都可以发主动发送消息、接收消息。) 为什么要使用reids实现? 其实就是计数法,这里采用的固定窗口算法。每个时间片有一个计数。但是现在服务端是分布式的,会有多个login进程,它们可能就不在一个机器上。所以这个 计数 必须放在所有进程都可以访问的地方,这里就是采用的redis了。所有进程上的排队逻辑都访问同一个reids仓库,进行计数。redis实现的分布式锁也是这个原理,把锁放在所有进程都可以访问的redis上。 我实现的登录排队系统的功能: 固定时间片中只允许一定数量(窗口大小)的玩家登录时间片和窗口大小可配置玩家排队时,告诉客户端当前排名和等待时间排队系统开启关闭可配置 固定窗口实现的登录限流流程图: Created with Raphaël 2.2.0 start 获取当前时间片 是否在登录队列 获取在登录队列的排名 否有剩余窗口? 抢占登录名额是否成功 登录成功 end 返回等待时间,登录等待 加入登录队列 yes no yes no yes no 代码实现redis实现的固定窗口算法限流 生产环境下的限流组件一般而言我们不需要自己实现限流算法来达到限流的目的,不管是接入层限流还是细粒度的接口限流其实都有现成的轮子使用,其实现也是用了上述我们所说的限流算法。 比如Google Guava 提供的限流工具类 RateLimiter,是基于令牌桶实现的,并且扩展了算法,支持预热功能。 阿里开源的限流框架Sentinel 中的匀速排队限流策略,就采用了漏桶算法。 Nginx 中的限流模块 limit_req_zone,采用了漏桶算法,还有 OpenResty 中的 resty.limit.req库等等。 参考限流算法概述 springboot限流机制 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |