幂等性设计

news2024/11/15 10:58:56

目录

前言

幂等性设计

幂等性设计处理流程

HTTP 幂等性

消息队列幂等性 机遇kafka 


前言

幂等性设计,就是说,一次和多次请求某一个资源应该具有同样的副作用。为什么我们要有幂等性操作?说白了,就两点:1、网络的不稳定性 2、服务状态不确定性,服务状态不仅有成功,失败,还有超时。超时又有多种原因引起的,有可能是网络抖动,也有可能是负载引起的。对于这种情况,需要做重试,重试的后果是服务被调用了多次,数据不对,业务当然出问题了。打个比方吧,我们网上购物,去支付时,网络原因超时,我们做重试,在我们发起重试后,网络好了,是不是有可能执行了两次,扣了两次钱。这样的情况其实有很多很多,还比如,订单服务重试,创建了两个同样的订单,等等。

系统超时,而调用方重试一下,给我们的系统带来不一致的副作用。遇到这样的情况,有几种情况处理

  1. 需要下游系统提供相应的查询接口。上游系统在 timeout 后去查询一下。如果查到了,就表明已经做了,成功了就不用做了,失败了就走失败流程

  2. 通过幂等性的方式。也就是说,把这个查询操作交给下游系统,我上游系统只管重试,下游系统保证一次和多次的请求结果是一样的

  3. 可以在一些特殊字段比如订单号设置成唯一索引,让数据表自己去判断

在这几种处理情况中,第一点主要是需要系统提供查询接口,第三点是根据数据库的特性设计。第二点比较比较特殊,我会详细讲解。

以上说的是业务的幂等性,还有HTTP 的幂等性,消息队列的幂等性主要谈论kafka 幂等性的设计。

幂等性设计

幂等性设计,需要有一个唯一的标识,来标志是同一个请求发起的。这个唯一的标识一般会用全局ID,才能做到全局唯一性。那么这个全局ID,怎么分配的。

  1. 可以有一个中心的发号系统分配,每个请求就先请求发好系统,简单的业务可以用redis incr 。但是这样会有很多问题,中心的发号系统会成为系统的瓶颈,每次请求都要去请求发号系统。若设计成集群,那么全局ID 可能会重复,这个方案比较适合流量小,设计成单体系统。

  2. 为了解决集群ID 冲突问题,们需要使用一个不会冲突的算法,比如使用 UUID 这样冲突非常小的算法。UUID 占用字符串空间大,索引效率低,生成的ID 太过于随机,索引为了保证数据的顺序性,可能会页的分裂。

  3. 在全局唯一 ID 的算法中,这里介绍一个 Twitter 的开源项目 Snowflake。它是一个分布式 ID 的生成算法。它的核心思想是,产生一个 long 型的 ID,

    1)41bits 作为毫秒数。大概可以用 69.7 年。

    2)10bits 作为机器编号(5bits 是数据中心,5bits 的机器 ID),支持 1024 个实例。

    3)12bits 作为毫秒内的序列号。一毫秒可以生成 4096 个序号。

它主要是有几部分组成:41bits 为毫秒级时间+5bits data center id+5 bits worked id+12 bits 毫秒内的技术

幂等性设计处理流程

方案一:我们可以先通过记录全局id查询。每次请求的时候,先去查,没有的话,就记录下来,有的话,就不处理请求,这样每次都必须先查询。

对于方案一是几个步骤:1、先查询全局id 2、插入数据。感觉这个设计保证数据的一致性是很难的。

1、我们把全局ID放在redis中流程图是这样的

这个妥妥的是有问题的,并发请求,查询Redis,没有,都会同时插入数据,舍弃

2、如果直接在数据表,先查询呢,可能有多个请求同时查询,没有,同时插入,也是有问题的。

这种方案需要加入分布式锁,客户端与客户端之间互斥只有一个客户端能够操作,加入了分布式锁无疑增加了系统的复杂度,而且效率也会低的。

方案二、其实我们可以直接用sql 语句操作。对于insert insert into … values … on DUPLICATE KEY UPDATE …

方案三 对于更新来说,如果只是状态更新,多次操作不会有副作用,是幂等的,比如 update table set status = “paid” where id = xxx and status = “unpaid”; 当然还有mvcc 乐观锁去处理,都是可以的,还是建议大家用全局id

HTTP 幂等性

http 有几个方法:GET、HEAD、OPTIONS、DELETE、POST、PUT ,http 幂等性与这几个方法有关:

GET 方法用于获取资源,没有副作用,是幂等的。比如 url ,不会改变资源的状态,调用n次返回的都不会改变资源,没有副作用。因此是幂等的

HTTP HEAD 和 GET 本质是一样的,区别在于 HEAD 不含有呈现数据,而仅仅是 HTTP 头信息,不应有副作用,也是幂等的。有的人可能觉得这个方法没什么用,其实不是这样的。想象一个业务情景:欲判断某个资源是否存在,我们通常使用 GET,但这里用 HEAD 则意义更加明确。也就是说,HEAD 方法可以用来做探活使用。

HTTP OPTIONS 主要用于获取当前 URL 所支持的方法,所以也是幂等的。若请求成功,则它会在 HTTP 头中包含一个名为“Allow”的头,值是所支持的方法,如“GET, POST”。

HTTP DELETE 方法用于删除资源,有副作用,但它应该满足幂等性。比如:DELETE url,调用一次和 N 次对系统产生的副作用是相同的,即删掉 ID 为 4231 的帖子。因此,调用者可以多次调用或刷新页面而不必担心引起错误。

HTTP POST 方法用于创建资源,所对应的 URI 并非创建的资源本身,而是去执行创建动作的操作者,有副作用,不满足幂等性。比如:POST url 的语义是在 url 下创建一篇帖子,HTTP 响应中应包含帖子的创建状态以及帖子的 URI。两次相同的 POST 请求会在服务器端创建两份资源,它们具有不同的 URI;所以,POST 方法不具备幂等性。

HTTP PUT 方法用于创建或更新操作,所对应的 URI 是要创建或更新的资源本身,有副作用,它应该满足幂等性。比如:PUT url 的语义是创建或更新 ID 为 4231 的帖子。对同一 URI 进行多次 PUT 的副作用和一次 PUT 是相同的;因此,PUT 方法具有幂等性。

所以,对于 POST 的方式,很可能会出现多次提交的问题,就好比,我们在论坛中发帖时,有时候因为网络有问题,可能会对同一篇贴子出现多次提交的情况。对此,一般的幂等性的设计如下。

  1. 首先,在表单中需要隐藏一个 token,这个 token 可以是前端生成的一个唯一的 ID。用于防止用户多次点击了表单提交按钮,而导致后端收到了多次请求,却不能分辨是否是重复的提交。这个 token 是表单的唯一标识。(这种情况其实是通过前端生成 ID 把 POST 变成了 PUT。)

  2. 然后,当用户点击提交后,后端会把用户提交的数据和这个 token 保存在数据库中。如果有重复提交,那么数据库中的 token 会做排它限制,从而做到幂等性。

  3. 当然,更为稳妥的做法是,后端成功后向前端返回 302 跳转,把用户的前端页跳转到 GET 请求,把刚刚 POST 的数据给展示出来。如果是 Web 上的最好还把之前的表单设置成过期,这样用户不能通过浏览器后退按钮来重新提交。这个模式又叫做 PRG 模式(Post/Redirect/Get)。

消息队列幂等性 机遇kafka 

生产端:从kafka 0.11.0 版本开始 每个生产端生成一个唯一的ID,在每条消息中生成一个sequence num 进行消息去重,只对在一个生产端内生产的消息有效。也可以在消息内容加个全局id 业务判断,和上面一样的。

后续补充

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

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

相关文章

品牌作为储蓄池:静态积累与长期价值

在瞬息万变的商业环境中,品牌不仅仅是一个简单的标识或名字,它更像是一个融合了静态积累与长期价值的综合储蓄池。品牌通过不断的积累,建立起深厚的市场基础和消费者信任,这些无形的资产为品牌的长期发展奠定了坚实的基础。品牌推…

【大厂AI课学习笔记NO.59】(12)过拟合与欠拟合

拟合就是调整参数和模型,让结果无限接近真实值的过程。 我们先来了解个概念: 偏差-方差窘境(bias-variance dilemma)是机器学习中的一个重要概念,它涉及到模型选择时面临的权衡问题。 偏差(Bias&#xf…

【二分查找】【C++算法】378. 有序矩阵中第 K 小的元素

作者推荐 视频算法专题 本文涉及的基础知识点 二分查找算法合集 LeetCode378. 有序矩阵中第 K 小的元素 给你一个 n x n 矩阵 matrix ,其中每行和每列元素均按升序排序,找到矩阵中第 k 小的元素。 请注意,它是 排序后 的第 k 小元素&…

ubuntu安裝Avahi发现服务工具

一、简介 解决设置固定ip后无法连接外网的问题,目前采用动态获取ip,可以不用设置设备的固定IP,直接可以通过域名来访问设备,类似树莓派的连接调试 二、安装 本文使用的是ubuntu23.10.1上安装 1.安装工具 sudo apt install av…

展览展会媒体传播的必要性,有哪些宣传方式?

传媒如春雨,润物细无声,大家好,我是51媒体网胡老师。 展览展会媒体传播的必要性在于扩大影响力、吸引观众和促进行业交流。通过媒体宣传,可以快速传递展会信息,提升品牌知名度,吸引更多潜在参展商和观众。…

【C语言】linux内核packet_setsockopt

一、中文注释 // 发送数据包函数。它尝试通过特定的网络设备队列直接传输一个skb(socket缓冲区)。 static int packet_direct_xmit(struct sk_buff *skb) {return dev_direct_xmit(skb, packet_pick_tx_queue(skb)); // 调用dev_direct_xmit函数&#x…

上位机图像处理和嵌入式模块部署(上、下位机通信的三个注意点)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 如果最终部署在客户现场的是一个嵌入式设备,那么上位机在做好了算法编辑和算法部署之后,很重要的一步就是处理上位机和下位…

Intel FPGA IP之LVDS SerDes IP学习

FPGA 视频数据输入输出直通工程: 屏:13.2吋8bit色深,屏幕分辨率为1440*192060,具有两个Port,每个Port有4个差分数据对与1个差分时钟对,差分对均支持LVDS协议芯片:Cyclone V系列FPGA目的&#x…

分布式ID生成策略-雪花算法Snowflake

分布式ID生成策略-雪花算法Snowflake 一、其他分布式ID策略1.UUID2.数据库自增与优化2.1 优化1 - 共用id自增表2.2 优化2 - 分段获取id 3.Reids的incr和incrby 二、雪花算法Snowflake1.雪花算法的定义2.基础雪花算法源码解读3.并发1000测试4.如何设置机房和机器id4.雪花算法时钟…

在Ubuntu22.04安装Fcitx5中文输入法教程(十分详细)

前言 书接上回,一时兴起将主力机的 Ubuntu 20.04 LTS 升级至了刚刚发布的 22.04 LTS。从 X 切换到 Wayland 、GNOME 从 3.36 升级至 42、Python 默认为 3.10 等等……使用太新的软件包反而暂时带来了麻烦,部分原有的软件和插件都不可用了。这其中就包括…

浅谈马尔科夫链蒙特卡罗方法(MCMC)算法的理解

1.解决的问题 计算机怎么在任意给定的概率分布P上采样?首先可以想到把它拆成两步: (1)首先等概率的从采样区间里取一个待定样本x,并得到它的概率为p(x) (2)然后在均匀分布U[0,1]上取一个值&a…

可视化管理的kanban插件 | Obsidian实践

继上一篇文章之后,有朋友提问说: 刚好,关于kanban插件的素材,是之前一早就准备好的,便快速整理成文,简单分享一下个人实践。 Prompt:项目流程管理看板,色彩鲜艳。by 通义万象 看板管…

C++调用lua函数

C 调用Lua全局变量(普通) lua_getglobal(lua, "width");int width lua_tointeger(lua,-1);lua_pop(lua,1);std::cout << width << std::endl;lua_close(lua); 这几行代码要放到lua_pcall(lua, 0,0,0);之后才可以. C给lua传递变量 lua_pushstring(lua, …

三、低代码平台-单据配置(单表增删改查)

一、业务效果图 主界面 二、配置过程简介 配置流程&#xff1a;业务表设计 -》业务对象建立-》业务单据配置-》菜单配置。 a、业务表设计 b、业务对象建立 c、业务单据配置 功能路径&#xff1a;低代码开发平台/业务开发配置/单据配置维护 d、菜单配置

【JavaEE】_Spring MVC 项目传参问题

目录 1. 传递单个参数 1.1 关于参数名的问题 2. 传递多个参数 2.1 关于参数顺序的问题 2.2 关于基本类型与包装类的问题 3. 使用对象传参 4. 后端参数重命名问题 4.1 关于RequestPara注解 1. 传递单个参数 现创建Spring MVC项目&#xff0c;.java文件内容如下&#xff…

【k8s存储--使用OpenEBS做持久化存储】

1、简介 使用OpenEBS&#xff0c;你可以将有持久化数据的容器&#xff0c;像对待其他普通容器一样来对待。OpenEBS本身也是通过容器来部署的&#xff0c;支持Kubernetes、Swarm、Mesos、Rancher编排调度&#xff0c;存储服务可以分派给每个pod、应用程序、集群或者容器级别&am…

Mybatis plus拓展功能-JSON处理器

目录 1 前言 2 使用方法 2.1 定义json实体类 2.2 在实体类中使用 1 前言 这是我最近学到的比较新奇的一个东西&#xff0c;数据库居然还可以存储JSON格式的数据&#xff0c;如下。虽然我感觉一般也没谁会这样干&#xff0c;但是既然有&#xff0c;那就当个科普讲一下Mybat…

【自然语言处理】NLP入门(三):1、正则表达式与Python中的实现(3):字符转义符及进制转换

文章目录 一、前言二、正则表达式与Python中的实现1.字符串构造2. 字符串截取3. 字符串格式化输出4. 字符转义符a. 常用字符转义符续行符换行符制表符双引号单引号反斜杠符号回车符退格符 b. ASCII编码转义字符进制转换2 进制8 进制10 进制16 进制进制转换函数 c. Unicode字符\…

每天学习一个Linux命令之gunzip

每天学习一个Linux命令之gunzip 在Linux系统中&#xff0c;有许多强大且常用的命令&#xff0c;其中之一是gunzip。gunzip命令用于解压缩.gz文件&#xff0c;它是gzip的伴生命令之一。本篇博客将详细介绍gunzip命令及其可用的选项&#xff0c;以帮助您更好地理解和使用这个命令…

运放设计选型中关注的参数-运算放大器选型参数

1、直流增益&#xff08;AVD&#xff09; 直流增益是运放最重要一个属性之一&#xff0c;其定义为输出电压的变化与输入电压变化之比值&#xff0c;通常用V/mV表示这个比值&#xff0c;例如&#xff0c;增益为30000&#xff0c;可表示为30V/mV&#xff0c;有些地方也会把增益用…