交易系统高并发下的幂等性设计原则

一、介绍

幂等性就是针对同一个请求,不管该请求被提交了多少次,该请求都将被视为同一个请求,服务端不应该将同一个请求进行多次处理,以确认处理逻辑的正确性,针对交易性系统幂等性的设计尤为重要,否则由于网络或服务器处理超时等问题,就会造成交易混乱,最严重的后果就是乱扣用户的钱,造成投诉満天飞。

 

二、客户端设计原则

系统设计时,一定是要从最坏的角度上去考虑,如网络问题、服务器问题,甚至于包括人为的攻击行为,如果纯粹从服务端的角度去做实现保证,一个是系统的复杂度会加大,二个也会对系统产生更大的并发压力,因而客户端的合理设计也非常重要,举一个示例:

用户在网页端或APP端(统称为客户端)上购买一个商品,通常都是以触发按钮的行为提交该请求,如果客户端没有做请求提交控制,那么由于网络原因或者系统繁忙等原因(这是非常常见的场景),没有在用户期望的时间之内响应,那么用户就会再次点击,那么这个请求又会发往服务端,那么服务端又会再次对这个请求进行处理。

针对这种场景,服务端就会接收处理到多个订单请求,从而产生多条不合理的用户订单。此时在客户端稍微优化一下,当用户的请求提交以后,将订单提交的请求按钮置为不可用的状态,待请求成功响应后跳转到下一步处理逻辑,或者是提单请求超时后再将订单提交按钮置为可用,提示用户上一次的提交可能已经失败,并允许用户再次提交。

当然客户端这样设计并不能完全做到幂等性原则,因为用户同样可以针对相同的订单执行多次提交,服务端如果没有做控制,还是会产生多个订单,只是让错误变得优雅了一点。这个时候需增加令牌策略,在下单之间,针对当前订单从服务端获取一个Token,每次提交的时候都从把该Token带上,针对同一个订单带上相同的值,这样服务端就可以根据该Token来判断是不是一个已经处理的了订单。

说了那么多,看文字太累,还是看图方便,来一个:

 三、服务端设计原则

根据不同的应用场景,服务端可以使用不同的解决方式,如:

1、数据库的乐观锁;
2、防重表;
3、token令牌;
4、分布式锁;
5、异步处理支付;

其中数据库的乐观锁和防重表的使用,都是涉及到数据的参与,在高并发的应用场景中,业务的判断逻辑尽量不要使用数据库参与,特别是RDBMS的参与,因为RDBMS天生具有不易扩展及事务处理属性,吞吐量上都会有相应的瓶颈,因而用数据库做业务逻辑的控制不是我的菜,这里就不会重点说这两种方式。

1、Token令牌+分布式锁的方式

Token是用于确定交易的唯一属性,也是服务端用于检验当前交易是否合法交易的依据,但是在分布式的复杂环境中,如果没有分布式锁的控制,同一笔交易就可能会被处理多次,因而为了确认交易的幂等性,Token令牌和分布式锁必须要一起使用。

实现逻辑步骤如下:

1、服务端根据交易前请求生成对应的Token,保存于服务端的Token库中,通常是缓存集群中,并将生成好的Token库下发给客户端;
2、客户端在每次请求的时候,都带上对应的Token;
3、服务端获取该Token对应的锁,如果获取成功,则继续下面的步骤;
4、判断是否该Token是否合法,如果合法则继续下一步;
5、处理真实的业务逻辑;
6、业务处理成功后,从缓存中删除该Token;
7、删除获取的分布式锁;

实现逻辑参见下图:

其中分布式锁的获取,可以通过Redis和Zookeeper实现,请参看笔者的另外两篇分别介绍通过Redis和Zookeeper实现分布式的文章:

集群环境中使用Redis实现分布式锁两种方式

集群环境中使用Zookeeper实现分布式幂等控制

2、异步处理

异步处理,通常的做法是将认为需要消费的交易,提交到消息队列中,并注册监听事件,待交易被处理完后,再由处理交易的应用回调注册的监听事件反馈处理的结果。交易处理的调度应用,需要负责对交易的处理符合幂等性的原则,将重复请求的交易请求做去重处理。

实现逻辑见下图:

从逻辑处理上可以看到,只要交易处理器足够多,处理速度也不一定会受到多少的影响,交易生产者和交易接收者甚至可以同步返回结果,当交易接收者接收处理结果超时后,再提示用户过一会儿查看交易的处理结果。

转载于:https://www.cnblogs.com/fenglibing/p/11026287.html

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

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

相关文章

工程中选择数据结构和算法的依据

1. 时间、空间复杂度不能和性能划等号 时间、空间复杂度不是时间执行和内存消耗的精确值。它们只是表示了随着数据量的增长,时间、空间的增长趋势。 代码的执行时间有时不跟时间复杂度成正比。我们常说算法是O(nlogn),O(n2n^2n2)这些都是基于大数据量(…

[密码学基础][每个信息安全博士生应该知道的52件事][Bristol Cryptography][第36篇]Index Calculus算法

这是一系列博客文章中最新的一篇,该文章列举了“每个博士生在做密码学时应该知道的52件事”:一系列问题的汇编是为了让博士生们在第一年结束时知道些什么。 我们这篇博客继续描述一种数学攻击,这种数学攻击被叫做Index Calculus(IC)算法。 注意这里Index…

DS博客作业07--查找

1.本周学习总结 1.思维导图 2.谈谈你对树结构的认识及学习体会。 查找是一种跟我们生活息息相关的算法,最典型的例子就是搜索引擎,而评价一种查找算法的优劣的关键就是查找速度,生活中我们往往要在大量数据查找自己所需要的东西,如…

easyUI学习笔记二

1&#xff0e; 拖拉大小 <!DOCTYPE html> <html> <head><title>easyui学习</title><script type"text/javascript" src jquery-easyui/jquery.min.js> </script><script type"text/javascript" src jquer…

C语言—每日选择题—Day62

隔一天更新解析 第一题 1. 在使用标准C库时&#xff0c;下面哪个选项使用只读模式打开文件&#xff1f; A&#xff1a;fopen("foo.txt", "r") B&#xff1a;fopen("foo.txt", "r") C&#xff1a;fopen("foo.txt", "w&…

[密码学基础][每个信息安全博士生应该知道的52件事][Bristol Cryptography][第37篇]The Number Field Sieve

这是一系列博客文章中最新的一篇&#xff0c;该文章列举了“每个博士生在做密码学时应该知道的52件事”:一系列问题的汇编是为了让博士生们在第一年结束时知道些什么。 转载链接&#xff1a;https://www.cnblogs.com/zhuowangy2k/p/12245636.html

大二下学期软件工程概论总结

软件工程概论这门课可以算是我本学期最辛苦的一门课了。但与此同时这门课给我带来的收获和其他课程相比&#xff0c;也不是一个量级的。 这学期我通过课上的学习与作业项目的完成过程&#xff0c;了解到软件开发由项目的确定到项目的需求分析&#xff0c;再到概要&#xff0c;详…

70. Climbing Stairs

输入&#xff1a;台阶数量n 输出&#xff1a;有多少种走法 规则&#xff1a;每次可以上一个台阶或者两个台阶 分析&#xff1a;想明白一件事情。如果现在在第k个台阶&#xff0c;那下一步可以到达第k1个台阶&#xff0c;或者第k2个台阶。换句话说想要到达第k个台阶&#xff0c;…

[密码学基础][每个信息安全博士生应该知道的52件事][Bristol Cryptography][第39篇]侧信道攻击和故障攻击有什么区别

这是一系列博客文章中最新的一篇&#xff0c;该文章列举了“每个博士生在做密码学时应该知道的52件事”:一系列问题的汇编是为了让博士生们在第一年结束时知道些什么。 侧信道攻击(Side-channel attacks, SCA)是一类攻击者尝试通过观察侧信道泄露来推测目标计算的信息。&#x…

面向对象:包装类、对象处理、类成员

包装类 Java是面向对象编程语言&#xff0c;但也包含了八种基本的数据类型&#xff0c;这八种基本的数据类型不支持面向对象的编程机制&#xff0c;基本的数据类型也不具备对象的特性&#xff1a;没有成员变量、方法被调用。所有类型的变量都继承Object类&#xff0c;都可以当成…

mysql-安装报错计算机中丢失MSVCR100.dll文件丢失

https://blog.csdn.net/weirdo_world/article/details/82393330

[密码学基础][每个信息安全博士生应该知道的52件事][Bristol52]40一般来说SPA和DPA的区别是什么

这是一系列博客文章中最新的一篇&#xff0c;该文章列举了“每个博士生在做密码学时应该知道的52件事”:一系列问题的汇编是为了让博士生们在第一年结束时知道些什么。 电磁(Electronmagnetic, EM)功率分析攻击被划分成两种类型的攻击&#xff0c;简单功率分析(SPA)或者差分功率…

LDAP入门

LDAP入门 首先要先理解什么是LDAP&#xff0c;当时我看了很多解释&#xff0c;也是云里雾里&#xff0c;弄不清楚。在这里给大家稍微捋一捋。首先LDAP是一种通讯协议&#xff0c;LDAP支持TCP/IP。协议就是标准&#xff0c;并且是抽象的。在这套标准下&#xff0c;AD&#xff08…

关于Java中的HashMap

1 容量总是2次幂 /*** Returns a power of two size for the given target capacity.*/static final int tableSizeFor(int cap) {int n cap - 1;n | n >>> 1;n | n >>> 2;n | n >>> 4;n | n >>> 8;n | n >>> 16;return (n <…

[密码学基础][每个信息安全博士生应该知道的52件事][Bristol52]41所有的侧信道分析都是能量分析吗

这是一系列博客文章中最新的一篇&#xff0c;该文章列举了“每个博士生在做密码学时应该知道的52件事”:一系列问题的汇编是为了让博士生们在第一年结束时知道些什么。 侧信道攻击(SCA)利用在密码算法的物理实现上下文中获得的信息&#xff0c;而不是针对理论弱点的经典密码分析…

spring学习(22):分层架构

pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0.0 …

[密码学基础][每个信息安全博士生应该知道的52件事][Bristol52]42蒙哥马利乘法,哪里泄漏侧信道路吗?

这是一系列博客文章中最新的一篇&#xff0c;该文章列举了“每个博士生在做密码学时应该知道的52件事”:一系列问题的汇编是为了让博士生们在第一年结束时知道些什么。 看看你的C代码为蒙哥马利乘法&#xff0c;你能确定它可能在哪里泄漏侧信道路吗? 几个月前(回到3月份)&…

spring学习(23):基础组件

Spring中的Component是一个通用注解&#xff0c;可用于任何bean对象&#xff0c;还可以细分为&#xff1a;Repository、Service、Controller&#xff0c;分别对应于DAO类&#xff08;持久层&#xff09;、Service类&#xff08;服务层&#xff09;、Controller&#xff08;控制…

Golang tcp转发 remoteAddr错误

Golang tcp 转发 第一版本 accept获取的Conn里的localAddr做为源地址&#xff0c;remoteAddr来做为目的地址 // tcpForward package mainimport ("fmt""net""os" )func TcpForward(port int) {lisPort : fmt.Sprint(":", port)listen,…

[密码学基础][每个信息安全博士生应该知道的52件事][Bristol52]43 为AES 对抗侧信道攻击的防御

这是一系列博客文章中最新的一篇&#xff0c;该文章列举了“每个博士生在做密码学时应该知道的52件事”:一系列问题的汇编是为了让博士生们在第一年结束时知道些什么。 为AES描述一些基础的&#xff08;可能无效&#xff09;的对抗侧信道攻击的防御 侧信道防御&#xff1a;为什…