接口幂等性的通用解决方案golang版

news2024/9/28 3:30:20

文章目录

  • 简介
  • 幂等性如何实现
    • 前端应当处理
    • 后端基于 token + redis 处理

简介

  • 接口的幂等性是指:
    用户对同一个操作发起多次请求,系统的设计需要保证其多次请求后结果是一致的。常见的如支付场景,连续快速点击两次支付 10 元,不应该扣费 20,第一次应该扣费成功,第二次则应该失败

  • 什么场景要考虑幂等性设计

    • 在现在公司里头,都在做分布式划分,一个大型系统会拆成比较多的模块,不同的模块用集群来部署,上游服务调用下游服务的形式,比如 rpc 调用,但是由于网络抖动等原因,可能会造成服务迟迟没有响应,用户端可能多次点击
    • 再一个就是支付场景也必须得考虑一下幂等性的问题
    • select 是天然幂等的操作,需要注意的是编辑相关的操作

幂等性如何实现

前端应当处理

前端一般对比如支付按钮需要加上频控,避免过快的连续点击

后端基于 token + redis 处理

想法:
两次针对同一订单的付款请求,如果每次这样的请求有一个唯一凭证,每次这个凭证访问到后端,看看 redis 有没有,有的话请求执行,redis 中删除凭证,没有的话请求失败。这样同样的 2 个请求就可以保证第一次成功第二次失败

在这里插入图片描述

具体步骤:

  • 步骤一:客户端要付款前,即在点击付款按钮前,客户端先发送一个请求获取 token,服务端生成一个全局唯一 id 作为 token,保存到 redis 中,同时把这个 id 返回给客户端
// 订单生成后,然后立马一个获取 token 的请求过来
// 从请求中获取用户 userId
userId := ...
// 雪花算法,或者大厂自己封装出来的依赖包的使用
token := ...
// redis 存储此全局唯一 id 并且设置过期时间 30 min
redisClient.Set(ctx, "order:token"+userId, token, time.Minute*30)
// 业务操作,返回 token 全局唯一数据
  • 步骤二:客户端点击付款,会带上这个 token id
  • 步骤三:服务端接收到 token id,去查 redis 能够查询到,于是放行后续业务操作,同时删除 redis 的 id
// 先通过请求参数拿到全局唯一 id
token := ...

// redis 通过 lua 执行原子操作判定此次请求是否执行还是失败返回,lua 原子操作的原因是防止并发时都执行了
scriptStr := "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end"
script := redis.NewScript(scriptStr) 
cmd := script.Run(ctx, redisClient, []string{"order:token"+userId}, token)

// 处理 err,失败返回客户端说明失败
if cmd.Err() != nil {
    // 返回扣款失败
}
// redis 原子操作查找删除是否成功
if v, _ := cmd.(int); v == 0 {
    // 不成功返回客户端说明扣款失败
}

// 执行后续业务逻辑操作
  • 步骤四:客户端紧接着快速点了第二次付款,但是这时候请求打到服务端发现 redis 已经没了此 token,因此第二次付款失败

注意:

  • 全局唯一 id 可以通过雪花算法,很多大公司也有封装的依赖包拿到全局 id,需要全局唯一 id 的原因也因为是分布式的环境,需要保证在集群中保证 id 唯一
  • 第一次和第二次付款请求需要保证 redis 多个操作的原子性,比如先查询 redis,能查到再删除 redis 这两步操作合在一起不具备原子性,因此需要用天然支持原子性的 lua 脚本去执行,这样能保证并发快速点击多次付款后不会出现这样的并发场景:一个执行到 if(是否能查到),另一个夜之星 if(是否能查到),这样就会导致都判定走后续的付款逻辑

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/375871.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

阶段八:服务框架高级(第三章:分布式缓存Redis)

阶段八:服务框架高级(第三章:分布式缓存Redis)Day-分布式缓存Redis0.学习目标1.Redis持久化1.1.RDB持久化 【重要】1.1.1.执行时机1.1.2.RDB原理1.1.3.小结1.2.AOF持久化【重要】1.2.1.AOF原理1.2.2.AOF配置1.2.3.AOF文件重写1.3.…

搜广推 WideDeep 与 DeepCrossNetwork (DCN) - 记忆+泛化共存

😄 这节来讲讲Wide&Deep与Deep&CrossNetwork (DCN)。从下图可看出WD非常重要,后面衍生出了一堆WD的变体。本节要讲的WD和DCN结构都非常简单,但其设计思想值得学习。 🚀 wide&deep:2016年,谷歌提出。 🚀 Deep&CrossNetwork (DCN):2017年,谷歌和斯坦…

刷题小抄1-2数之和

时间复杂度和空间复杂度 对于一个算法高效性的评估,分为时间复杂度与空间复杂度两种,在算法优化到极致的情况下,只能舍弃时间来换取空间,或者舍弃空间来换取时间,故而两者可以说是互斥关系 时间复杂度衡量的是算法运行的速度,而空间复杂度衡量的是算法运行所需要的额外内存空…

【Ap AutoSAR入门与实战开发03】-【Ap_s2s模块02】:到底什么是基于信号,什么是基于服务,两者的主要区别是什么?

总目录链接==>> AutoSAR入门和实战系列总目录 文章目录 1 基于信号的通信2 基于服务的通信3 面向服务设计举例在【Ap_s2s模块01】中我们大概讲述了,为什么要有s2s模块,并且简单的阐述了基于信号的通信和基于SOME/IP的服务的通信,我们接下来详细分析一下这两个概念。…

Torch单独层赋值

20230227 - 引言 对于torch中的权值初始化方式,以往都是采用默认的方式,或者利用初始化库里面的函数。但是如果想尝试一些自己的想法,那就必须自己来填充这部分数据,例如看到的内容,利用PCA的公式来对权值进行填充。…

CSGO社区服务器搭建架设服务器配置以及环境准备

CSGO社区服务器搭建架设服务器配置以及环境准备 CSGO作为一款射击动作游戏还原场景真实性广受大批玩家的热爱,很多小伙伴也有想过自己搭建的话需要知道那些东西。 我是艾西,今天跟大家聊聊搭建架设前我们需要知道的事情: Windows&#xff1…

【谷歌grc】recaptcha browser-error 错误

grc 谷歌人机验证错误 https://www.google.com/recaptcha/api/siteverif 返回错误信息 browser-error [{"success": false,"error-codes": ["browser-error"] }]之前都是调通能用的,突然之间就不能用了,查了半天也没有找…

前端实现压缩图片的功能(vue-element)

前言: 随着现在手机像素,拍照功能越来越好,随之而来的是本地图片越来越大,那么如何更好的将本地图片上传到后端接口呢?这是后台管理系统常见的场景和头疼的问题,这里分享下个人的方法。 实现效果&#xff…

java多线程(八)线程等待与线程唤醒2

三、wait(long timeout)和notify() wait(long timeout)会让当前线程处于“等待(阻塞)状态”,“直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量”,当前线程被唤醒(进入“就绪状态”)。 下面的示例就是演示…

入职数据分析公认的好书|建议收藏

众所周知,数据分析经常出现在我们的日常生活中,各行各业都需要数据分析。可你知道什么是数据分析?它在企业里到底扮演什么角色?以及如果我们自己也想拥有数据分析的能力,以便更好的满足数据分析的需求,我们…

系列六、存储引擎

一、存储引擎介绍 大家可能没有听说过存储引擎,但是一定听过引擎这个词,引擎就是发动机,是一个机器的核心组件。 比如,对于舰载机、直升机、火箭来说,他们都有各自的引擎,是他们最为核心的组件。而我们在选…

vue脚手架多页自动化生成实践

前言 在前端开发过程中,常常面对多种业务场景。到目前为止,前端对于不同场景的处理通常会采用不同的渲染方案来组合处理,常见的渲染方案包括:CSR(Client Side Rendering)、SSR(Server Side Rendering)、SSG(Static Site Generati…

2023年房地产行业研究报告

第一章 行业发展概况 房地产业是指以土地和建筑物为经营对象,从事房地产开发、建设、经营、管理以及维修、装饰和服务的集多种经济活动为一体的综合性产业,是具有先导性、基础性、带动性和风险性的产业。主要包括:土地开发,房屋的…

Vue3 -- PDF展示、添加签名(带笔锋)、导出

文章目录笔锋签名方案一实现要点实现过程组件引用页面元素添加引用实现代码效果展示缺点方案二修改页面元素替换引用修改代码效果展示完整代码地址实现功能的时候采用了两个方案,主要是第一个方案最后的实现效果并不太理想,但实现起来比较简单&#xff0…

JavaScript手写题

一、防抖 function debounce(fn, delay200) {let timeout null; // 定时器控制return function(...args) {if (timeout) { // 定时器存在,表示某个动作之前触发过了clearTimeout(timeout); // 清除定时器timeout null;} else {// 对第一次输入立即执行fn.apply…

【Leetcode 剑指Offer】第 5 天 查找算法(中等)

查找算法剑指 Offer 04. 二维数组中的查找剑指 Offer 11. 旋转数组的最小数字剑指 Offer 50. 第一个只出现一次的字符Python字典基础哈希表(python中是dict())有序哈希表第一个中等,后两个简单题。剑指 Offer 04. 二维数组中的查找 题&#…

Node.js的研究和应用

首先我们要知道什么是node.js? Node.js采用谷歌的V8引擎,是一个服务器端的、非阻断式I/O的、事件驱动的 JavaScript运行环境。 一、Node.js架构具体包含什么呢?咱们从一个图来看看会更加明白。 natives modules: 1.当前层内容由js实现 。…

不使用implements关键字实现实现类(类似于mapper)

首先,说明一下功能需求,平时定义一个接口,就要使用implements关键字来实现接口。那么,当不使用此关键字的时候,是否也能使相关接口也能够绑定实现类呢? 答案是肯定的。 此篇文章的主要功能有两个&#xf…

知识类问答数据集资源对外开放:百万级百度知道、社区问答及六大领域级小规模语料概述

随着chatgpt的火热,中文知识类问答数据集由收到诸多关注,其作为高质量的QA数据,可以用于SFT阶段以及pretrain预训练阶段。 本文主要介绍目前开源可下载的两个较大规模的知识类数据集,包括147万百度知道知识类数据集、425万社区问…

IOS逆向前期环境准备笔记

ios系统由于效验问题,只能升级不能降级,需要特别注意, 刷系统可以在爱思上搞定; 越狱推荐使用u盘镜像及本地启动盘制作: 注意,要进去bios,关闭安全启动,不然直接失败: Checkra1n镜…