利用Redis对含有分页参数的API接口做调用次数限制

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: 利用Redis对含有分页参数的API接口做调用次数限制

 背景 - 限制接口调用次数:

       提供内部调用的全量拉取数据接口,以用户appid作为维度区分,一定时间段内(比如1小时),查询某一接口的appid和limit、offset等组合参数只能查询一次,多次查询相同组合参数则返回错误值。

思路:

       采用string类型,key就是模块名:api_limiter_xxx(根据需要自定义key名称),value就是当前可以访问的页数(每次访问成功都自增1)。第一次访问某接口时,若key不存在,那么就添加;若存在,则获取当前redis中对应key的"页数值",并与入参Limit和Offset计算后的页数结果进行比较,若相等则调用成功,反之调用失败。

其中,在设置key和value的时候也要设置"过期时间"。所以关键在于 SETNX 的使用,若存在,则匹配计算的页数与redis中的计数器页数是否相等,若不存在,则设置kv。

注意:其中每次set key的值的时候,过期时间的处理。这里在set之前先通过TTL获取key剩余的过期时间,然后set时再带入接下来剩余的时间即可,避免每次都重新设置固定的过期时间。

    1. 初始时,redisPageCnt = 1
    2. 首次调用接口时,Limit=10,Offset=0,calculateCnt = (Limit + Offset) / Limit = 1;redisPageCnt=1
    3. 此时 calculateCnt = redisPageCnt 相等,redisPageCnt++,redisPageCnt = 2
    4. 再次调用接口时,Limit=10,Offset=10,calculateCnt = (Limit + Offset) / Limit = 2;redisPageCnt=2
    5. 此时 calculateCnt = redisPageCnt 相等,redisPageCnt++,redisPageCnt = 3
    6. ...

           这样的话就可以按页数从前往后递增,每页在限制的超时时间内(1小时)访问一次。在key的超时时间内,访问过的页数也不能再次访问,除非redis中的key超时时间失效。

    请求示例:

    var req = TestReq{ Appid: 1256299843, Limit: 10, Offset: 20, }

    packagemainimport (
    "fmt""strconv""time""github.com/go-redis/redis")
    // 限流:针对含有分页参数的接口,对于不同"Limit和Offset"组合做限制,避免某个用户大量请求影响后台服务处理其他正常请求// 示例://  var req = TestReq{//      Appid:  1256299843,//      Limit:  10,//      Offset: 20,//  }typeTestReqstruct {
    Appiduint64LimitintOffsetint}
    funcAPILimiter(reqTestReq) (errerror) {
    ifreq.Limit!=10 { // 校验入参,暂时写死,根据情况修改fmt.Println("req.Limit format err: ")
    // return response ...return    }
    redisCli :=redis.NewClient(&redis.Options{
    Addr:     "xxx.xxx.xxx.xxx:3306", // ip:portPassword: "yundingyd",
    PoolSize: 10,
        })
    // pong, err := redisCli.Ping().Result()// 不存在 -> 初始化;存在 -> 不处理redisKey :="api_limiter_"+strconv.FormatUint(req.Appid, 10)
    isOk, err :=redisCli.SetNX(redisKey, 1, time.Hour).Result() // 限制超时1小时,Result()针对不同命令自动转换对应结果iferr!=nil&&err!=redis.Nil&&isOk==false {
    fmt.Println("APILimiter SetNX err: ", err)
    // return response ...return    }
    calculatePageCnt := (req.Limit+req.Offset) /req.LimitredisPageCnt, err :=redisCli.Get(redisKey).Int()
    iferr!=nil&&err!=redis.Nil&&isOk==false {
    fmt.Println("APILimiter redisCli.Get err: ", err)
    // return response ...return    }
    ifcalculatePageCnt!=redisPageCnt {
    fmt.Printf("接口调用失败:当前Limit和Offset对应的页数无效: limit=%d, offset=%d, calculateCnt=%d, redisPageCnt=%d\n", req.Limit, req.Offset, calculatePageCnt, redisPageCnt)
    // return response ...return    }
    deferfunc() {
    iferr==nil { // 具体的业务逻辑,期间可能会产生err,只有err为空时才执行以下逻辑~// 先查询当前key的剩余过期时间timeDuration, err :=redisCli.TTL(redisKey).Result()
    iferr!=nil&&err!=redis.Nil {
    fmt.Println("redisCli.TTL err: ", err)
    // return response ...return            }
    // 再设置当前key的剩余过期时间isOk, err :=redisCli.Set(redisKey, redisPageCnt+1, timeDuration).Result() // page + 1iferr!=nil&&err!=redis.Nil&&isOk!="OK" {
    fmt.Println("redisCli.Set err: ", err)
    // return response ...return            }
    fmt.Println("接口调用成功!!!")
            }
        }()
    // 具体的业务逻辑(期间可能会产生err,除非期间err为nil,否则defer函数不执行 page+1 等操作):// ...return}
    funcmain() {
    varreq=TestReq{
    Appid:  1256299843,
    Limit:  10,
    Offset: 20,
        }
    err :=APILimiter(req)
    iferr!=nil {
    fmt.Println("APILimiter err: ", err)
    return    }
    }

    image.gif


    相关实践学习
    基于Redis实现在线游戏积分排行榜
    本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
    云数据库 Redis 版使用教程
    云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
    目录
    相关文章
    |
    6天前
    |
    缓存 负载均衡 API
    抖音抖店API请求获取宝贝详情数据、原价、销量、主图等参数可支持高并发调用接入演示
    这是一个使用Python编写的示例代码,用于从抖音抖店API获取商品详情,包括原价、销量和主图等信息。示例展示了如何构建请求、处理响应及提取所需数据。针对高并发场景,建议采用缓存、限流、负载均衡、异步处理及代码优化等策略,以提升性能和稳定性。
    |
    10天前
    |
    编解码 监控 API
    直播源怎么调用api接口
    调用直播源的API接口涉及开通服务、添加域名、获取API密钥、调用API接口、生成推流和拉流地址、配置直播源、开始直播、监控管理及停止直播等步骤。不同云服务平台的具体操作略有差异,但整体流程简单易懂。
    |
    19天前
    |
    JSON NoSQL Java
    springBoot:jwt&redis&文件操作&常见请求错误代码&参数注解 (九)
    该文档涵盖JWT(JSON Web Token)的组成、依赖、工具类创建及拦截器配置,并介绍了Redis的依赖配置与文件操作相关功能,包括文件上传、下载、删除及批量删除的方法。同时,文档还列举了常见的HTTP请求错误代码及其含义,并详细解释了@RequestParam与@PathVariable等参数注解的区别与用法。
    |
    23天前
    |
    人工智能 自然语言处理 PyTorch
    Text2Video Huggingface Pipeline 文生视频接口和文生视频论文API
    文生视频是AI领域热点,很多文生视频的大模型都是基于 Huggingface的 diffusers的text to video的pipeline来开发。国内外也有非常多的优秀产品如Runway AI、Pika AI 、可灵King AI、通义千问、智谱的文生视频模型等等。为了方便调用,这篇博客也尝试了使用 PyPI的text2video的python库的Wrapper类进行调用,下面会给大家介绍一下Huggingface Text to Video Pipeline的调用方式以及使用通用的text2video的python库调用方式。
    |
    22天前
    |
    JavaScript API
    |
    22天前
    |
    JSON JavaScript API
    (API接口系列)商品详情数据封装接口json数据格式分析
    在成长的路上,我们都是同行者。这篇关于商品详情API接口的文章,希望能帮助到您。期待与您继续分享更多API接口的知识,请记得关注Anzexi58哦!
    |
    6天前
    |
    JSON API 开发者
    1688API商品详情接口如何获取
    获取 1688 API 商品详情接口的步骤包括:1. 注册开发者账号;2. 了解接口规范和政策;3. 申请 API 权限;4. 获取 API 密钥;5. 实现接口调用(选择开发语言、发送 HTTP 请求);6. 处理响应数据。通过这些步骤,可以顺利调用 1688 的商品详情 API。
    |
    6天前
    |
    缓存 监控 API
    微服务架构下RESTful风格api实践中,我为何抛弃了路由参数 - 用简单设计来提速
    本文探讨了 RESTful API 设计中的两种路径方案:动态路径和固定路径。动态路径通过路径参数实现资源的 CRUD 操作,而固定路径则通过查询参数和不同的 HTTP 方法实现相同功能。固定路径设计提高了安全性、路由匹配速度和 API 的可维护性,但也可能增加 URL 长度并降低表达灵活性。通过对比测试,固定路径在性能上表现更优,适合微服务架构下的 API 设计。
    |
    2月前
    |
    安全 API 开发者
    Web 开发新风尚!Python RESTful API 设计与实现,让你的接口更懂开发者心!
    在当前的Web开发中,Python因能构建高效简洁的RESTful API而备受青睐,大大提升了开发效率和用户体验。本文将介绍RESTful API的基本原则及其在Python中的实现方法。以Flask为例,演示了如何通过不同的HTTP方法(如GET、POST、PUT、DELETE)来创建、读取、更新和删除用户信息。此示例还包括了基本的路由设置及操作,为开发者提供了清晰的API交互指南。
    99 6
    |
    3月前
    |
    存储 JSON API
    淘系API接口(解析返回的json数据)商品详情数据解析助力开发者
    ——在成长的路上,我们都是同行者。这篇关于商品详情API接口的文章,希望能帮助到您。期待与您继续分享更多API接口的知识,请记得关注Anzexi58哦! 淘宝API接口(如淘宝开放平台提供的API)允许开发者获取淘宝商品的各种信息,包括商品详情。然而,需要注意的是,直接访问淘宝的商品数据API通常需要商家身份或开发者权限,并且需要遵循淘宝的API使用协议。
    淘系API接口(解析返回的json数据)商品详情数据解析助力开发者