博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
交易系统高并发下的幂等性设计原则
阅读量:5126 次
发布时间:2019-06-13

本文共 1717 字,大约阅读时间需要 5 分钟。

一、介绍

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

 

二、客户端设计原则

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

用户在网页端或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实现分布式的文章:

2、异步处理

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

实现逻辑见下图:

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

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

你可能感兴趣的文章
Knozen:新型职场社交评论匿名应用,已获多家风投投资
查看>>
第三次个人赛题目2 【多项式输出格式】
查看>>
剑指offer 重建二叉树
查看>>
排序算法之冒泡排序
查看>>
so打包进APK
查看>>
cocos2d 走动椭圆
查看>>
Spring 构造注入 传參数
查看>>
三白话经典算法系列 Shell排序实现
查看>>
启动文件、简单的消息框
查看>>
素数倒数的级数发散性的一个证明
查看>>
python初识
查看>>
《网络攻防》第6周作业
查看>>
Linux学习——echo和read命令用法
查看>>
WPF中的数据绑定Data Binding使用小结
查看>>
java读写注册表的两种方式,Preferences与jRegistry
查看>>
轻量级web富文本框——wangEditor使用手册(4)——配置下拉菜单 demo
查看>>
[C++程序设计]用指向数组的指针作函数参数
查看>>
深入理解C# 静态类与非静态类、静态成员的区别 [转载]
查看>>
套接字结构汇总
查看>>
JS脚本病毒调试脚本-Trojan[Downloader]:JS/Nemucod
查看>>