【IT老齐020】接口幂等性

发布时间 2023-05-05 23:43:54作者: Faetbwac

【IT老齐020】接口幂等性

1683295249659

传统方案

业务代码增加前置判断

if(数据未更新){
	更新数据
}

缺点

  • 判断因素过多
  • 技术问题干扰业务代码

通用方案

幂等表

架构方案 nginx+lua+redis

  • 请求经过nginx转发到redis,redis查找幂等表是否存在请求id(uuid或请求hash)对应的key
    • 幂等表不存在请求id
      • lua脚本保存到幂等表并设置请求状态(PROC)及存活时间
      • 处理请求,处理结束后更新幂等表请求状态(OK)(无论请求结果如何)并返回结果
    • 幂等表存在请求id
      • 直接返回201,前台自动排除

使用自定义注解,利用@AOP After通知,更新Redis状态

1683295837742

1683296142153

1683296221272

过期时间作用

  • redis占用内存,幂等表数据过多,会导致系统响应变慢。设置过期时间使数据总量处于低水位
  • 服务处理未即使更新redis幂等表。设置过期时间使请求重新可用

优点

  • 后台服务无代码侵入,无需修改业务逻辑

缺点

  • 前台应用要针对幂等进行改造
  • 架构复杂度增加,需要额外部署Nginx、Redis

拓展

  • 数据量大的接口保证幂等?
    • 首先大多数幂等有效期不需要很长时间,在业务允许的前提下可以考虑缩短过期时间,其次数据量大是不怕的,怕是在数据间的耦合太大导致服务无法水平扩展,只要能保证扩展,qps就能打下来
  • 如果应用系统发出一个新请求,应用网关成功将requestId存入redis,而此时网关向数据服务转发请求时失败。在key失效前应用系统的重试机制是不是不管用了?网关转发请求到数据服务,网关自身有重试吗?
    • 网关不做重试否则幂等就被破坏了。 由网关转发失败导致的情况确实有,极少数不考虑
  • 区分那些url请求是要幂等处理呢?
    • 查询的接口可以在请求的时候不带requestId,网关判断没有id就不存redis,切面判断没有id就不去该redis
  • 加在nginx去处理会增加复杂度,直接用redis分布式锁不是也可以实现么?为什么不用redis分布式锁呢?这里nginx去redis进行nx操作,实际上也是分布式锁的一种实现
    • 降低服务端的负荷,让无效的请求不要穿透到服务端处理。
  • 后端发生错误时,redis一直会保持proc,retry的请求进不来,而redis的过期又必须覆盖retry的最大尝试时间,不然在极端情况下最后的retry还是会被错误的处理。如何解决?
    • 在后端程序发生了非逻辑错误的时候,比如依赖的其他组件或服务发生错误时,必须去处理redis中数据的状态或删除,以保证后续的retry请求能进来。