解决方案我们希望能够唯一地识别每个请求 。此外 , 我们需要准确跟踪和管理特定请求在其生命周期中的位置 。
我们在多种支付服务中实施并使用了“Orpheus” , 这是一种通用的幂等库 。Orpheus是传说中的希腊神话英雄 。
我们选择了实现幂等库作为解决方案 , 因为它提供低延迟 , 同时仍然提供高速变更的产品代码和低速变更的系统管理代码之间的隔离 。在高层次上 , 它包含以下:
- 幂等key被传递到框架中 , 表示单个幂等请求
- 始终从主数据库读取和写入(为了一致性)幂等信息表
- 通过使用JAVA lambda组合数据库事务 , 确保原子性
- 错误被分类为“可重试”或“不可重试”
最小化数据库提交幂等系统的关键要求之一是只产生两个结果 , 即成功或失败 , 具有一致性 。否则 , 数据有偏差可能导致数小时排查错误时间和付款出问题 。由于数据库提供ACID属性 , 因此数据库事务可以有效地用于原子写入 , 确保一致性 。一次数据库提交可以保证其作为一个单元的一致性 。
Orpheus假设每个标准API请求都分为三个不同的阶段:Pre-RPC , RPC和Post-RPC 。
“RPC”是指客户端向远程服务器发出请求并等待该服务器响应的过程 。在支付API的上下文中 , 我们将RPC称为对下游服务的请求 , 其可以包括外部支付服务和收单银行等 。简而言之 , 如下是每个阶段发生的事情:
- Pre-RPC:付款请求的详细信息记录在数据库中 。
- RPC:请求通过网络对外部服务进行实时处理 , 并收到响应 。这是一个执行幂等计算或RPC的过程(例如 , 如果是重试尝试 , 则首先查询事务状态) 。
- Post-RPC:来自外部服务的响应的详细信息记录在数据库中 , 包括其是否成功以及错误请求是否可重试 。
- 在Pre-RPC和Post-RPC阶段 , 没有远程服务交互
- RPC阶段中没有数据库交互
我们还想要说明单个API请求可能包含多个RPC 。Orpheus支持多RPC请求 , 但在这篇文章中 , 我们只想用简单的单RPC案例来说明我们的思考过程 。
如下面的示例图所示 , 所有Pre-RPC和Post-RPC阶段中的数据库提交都合并为一个数据库事务,这确保了原子性。动机是系统应该以可恢复的方式出现故障 。例如 , 如果在多次数据库提交过程中有几次失败 , 那么系统地跟踪每个失败发生的位置将非常困难 。请注意 , 所有网络通信(RPC)都与数据库事务明确分开 。
文章插图
这里的数据库提交包括幂等库的数据库提交和应用程序数据库提交 , 所有这些提交都组合在同一个代码块中 。如果不小心组织 , 这里的代码就会非常混乱 。我们认为产品开发人员不应该负责保证幂等库的操作 。
Java Lambdas 组合事务值得庆幸的是 , Java lambda表达式可以将多个提交无缝地组合成单个数据库事务 , 也不会影响可测试性和代码可读性 。
下面是一个示例 , 简化了Orpheus的使用 , 其中Java lambdas如下:
public Response processPayment(InitiatePaymentRequest request, UriInfo uriInfo)
throws YourCustomException {
return orpheusManager.process(
request.getIdempotencyKey,
uriInfo,
// 1. Pre-RPC
-> {
// Record payment request information from the request object
PaymentRequestResource paymentRequestResource = recordPaymentRequest(request);
return Optional.of(paymentRequestResource);
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 大家都在说的分布式系统到底是什么?
- 支付开发填坑记之支付宝
- 怎么用集分宝 集分宝在支付的时候怎么使用
- DNS即域名系统怎样工作?看这位“翻译官”如何转换域名和IP地址
- 软件架构-解密电商系统-秒杀的原理和开发思路
- 智能电视两大系统UI对比,原来系统体验好和无广告才是重中之重
- 科技涨价板块的核心个股名单
- 如何更改微信乘车码支付方式
- 微信支付电子小票上线
- carplay是什么功能