0、常识
分布式系统数据不一致性问题是不可避免,于是对于重要交易(跟钱打交道的,操作不具有“幂等性”的)的都需要对账,对账就有个对账日期(对账日期必须是对账各方共享的,一致认可的),这个日期不能采用自然时间,因为各个子系统的本地自然时间总存在一定的差异,再者交易还有时延,跨国交易还有时区问题。因此,对账日期希望由某个子系统分配,然后在交易请求或响应时发给其他子系统,实现共享。于是,分布式应用中,一笔交易往往需要: 发送方自然时间; 接受方自然时间; 财务时间(对账时间)。
1、具体场景
第三方支付机构(比如UMPAY,支付宝)要给银联发送一个扣款请求,银联顺利扣掉用户银行卡中的钱,给第三方支付机构发送“成功”的响应,并在响应中给出了该笔交易的对账日期。
要知道银联的报文格式都是ISO8583的,一般在第15域给出个格式为MMdd的对账日期。(注意:不是yyyyMMdd,省了个年份,跨年的时候就容易出错)。
而第三方支付机构由于是后来发展的,意识到类似千年虫问题的存在,于是在数据库设计时对账日期是以yyyyMMdd存放的。
于是接下来一个很自然的工作是:当银联给出MMdd的对账日期,第三方支付机构应该弄出个yyyyMMdd的对账日期。
2、款年时可能出现的问题
前提:银联和第三方支付机构的结算是按日结算
(1)财务日期超前自然日期(提前日切)
【边界情况描述】
当前自然时间2008-12-31 23:00:00,但是银联的财务日期提前切到2009-01-01;第三方支付机构给银联发一个扣款请求,并收到成功响应,财务日期给的是“0101”(MMdd格式);
【第三方支付机构补齐年份】
第三方支付机构依据本地系统时间2008-12-31 23:00:00,对“0101”补齐年份,得到SettlementDate=20080101,而当前自然日期是NaturalDate=20081231;
由于双方协商的结算周期是“按日”,那么正常情况下SettlementDate与NaturalDate最多相差一天,现在却出现:Distance = |SettlementDate - NaturalDate| >> SettlementPeriod,于是判断本次计算出现了因跨年导致的年份不对的情况。if(SettlementDate < NaturalDate) SettlementDate.year += 1;最终得到的对账日期是:20090101
(2)财务日期滞后自然日期(滞后日切)
【边界情况描述】
当前自然时间2009-01-01 00:10:00,但是银联的财务日期尚未做日切,财务日期是2008-12-31;第三方支付机构给银联发一个扣款请求,并收到成功响应,财务日期给的是“1231”(MMdd格式);
【第三方支付机构补齐年份】
第三方支付机构依据本地系统时间2009-01-01 00:10:00,对“1231”补齐年份,得到SettlementDate=20091231,而当前自然日期是NaturalDate=20090101;
由于双方协商的结算周期是“按日”,那么正常情况下SettlementDate与NaturalDate最多相差一天,现在却出现:Distance = |SettlementDate - NaturalDate| >> SettlementPeriod,于是判断本次计算出现了因跨年导致的年份不对的情况。if(SettlementDate > NaturalDate) SettlementDate.year -= 1;最终得到的对账日期是:20081231
(3)第三方支付机构得到“补齐年份”的算法
String-yyyyMMdd SettlementDateNormalization(String MMdd-BankUnion) {
String SettlementDate = System.currentTime("yyyy") + MMdd-BankUnion;
String NaturalDate = System.currentTime("yyyyMMdd");
long Distance = |SettlementDate - NaturalDate|;
long SettlementPeriod = 1天;//双方协议约定的对账周期常量
if(Distance >> SettlementPeriod) {//当时间差远远大于对账周期,则说明出现跨年的问题了
if(SettlementDate < NaturalDate) SettlementDateNormalized = SettlementDate.yyyy + 1;
else SettlementDateNormalized = SettlementDate.yyyy - 1;
}
return SettlementDateNormalized;
}
(4)分析(3)中的算法
虽然双方协议约定的对账周期常量是1天,但是银联日切工作可能是人工干预的,这样可能因为认为因素导致好几天都没做日切,比如:当前自然时间已经是20090710号了,但是银联的财务日期却还是20090707号。按照上面的算法,第三方支付机构在补齐年份时,输入财务日期:“0707”,初步补齐是SettlementDate=“20090707”,本地自然日期是NaturalDate=“20090710”,两者之差Distance > SettlementPeriod;同时SettlementDate < NaturalDate,于是被规格化成“20100707”。
应该注意到跨年导致的Distance会远远大于SettlementPeriod,这个Distance都快接近一年了。随意算法:if(Distance >> SettlementPeriod)的“远远大于”的具体实施应该是:
if(Distance > SettlementPeriod * Tolerance=7) 最多容忍7天不做日切,或提前7天做日切。
String-yyyyMMdd SettlementDateNormalization(String MMdd-BankUnion) {
String SettlementDate = System.currentTime("yyyy") + MMdd-BankUnion;
String NaturalDate = System.currentTime("yyyyMMdd");
long Distance = |SettlementDate - NaturalDate|;
long SettlementPeriod = 1天;//双方协议约定的对账周期常量
int Tolerance = 7;//对账日期切换相对协议滞后或提前的容忍度
if(Distance > SettlementPeriod * Tolerance) {//当时间差远远大于对账周期,则说明出现跨年的问题了
if(SettlementDate < NaturalDate) SettlementDateNormalized = SettlementDate.yyyy + 1;
else SettlementDateNormalized = SettlementDate.yyyy - 1;
}
return SettlementDateNormalized;
}
(5)java代码
/**
* @param bankCheckDate 银行传入的清算日期,不带年的
* @return 本地补充一个带年的清算日期
* */
protected String caculateBankCheckDate(String bankCheckDate) throws ParseException {
String yyyyMMdd = null;
String yyyy = Util.strDateTime("yyyy");
String stldate = yyyy + bankCheckDate;
SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMdd");
long slttime = fmt.parse(stldate).getTime();
long currtime = System.currentTimeMillis();
long dis = slttime - currtime;
long day1 = 24 * 3600 * 1000;
int tolerance = 7;
if (Math.abs(dis) >= day1 * tolerance) {
if (slttime < currtime) {
yyyy = String.valueOf(Integer.parseInt(yyyy) + 1);
stldate = yyyy + bankCheckDate;
} else {
yyyy = String.valueOf(Integer.parseInt(yyyy) - 1);
stldate = yyyy + bankCheckDate;
}
}
yyyyMMdd = stldate;
return yyyyMMdd;
}
(注:有时间需要整理下表达)
分享到:
相关推荐
爬虫python分布式网络爬虫源代码.zippython分布式网络爬虫源代码.zippython分布式网络爬虫源代码.zippython分布式网络爬虫源代码.zippython分布式网络爬虫源代码.zippython分布式网络爬虫源代码.zippython分布式网络...
"分布式置换流水车间调度问题研究概述" 分布式置换流水车间调度(DPFSP)问题是一个非常重要的研究领域,旨在解决分布式系统中的流水车间调度问题。该问题的目标是寻找一个最优的调度方案,使得作业在机器上的完成...
商剑分布式网络蜘蛛,性能高速运转,能耗尽全部带宽,可批量采集海量数据的网页,若几百台服务器安装商剑分布式网络蜘蛛,分块同时抓取整个WEB不同站点,短时期内可以抓取100亿网页!商剑分布式网络蜘蛛,是大型搜索...
萤火虫分布式电源优化,萤火虫优点,C,C++源码
分布式Python爬虫是现代网络数据抓取领域中的一个重要技术,它允许我们利用多台计算机的资源,高效地处理大规模的网页抓取任务。在本文中,我们将深入探讨分布式Python爬虫的基本概念、工作原理以及如何实现。 首先...
萤火虫分布式电源优化,萤火虫优点,C,C++源码.rar
这些特征要求分布式交易平台在设计上需要解决大规模数据处理、实时性问题、数据一致性和系统稳定性等关键问题。 3. 分布式交易平台的技术组成:招商银行分布式交易平台建设包括了高性能运行框架、平台化管理的服务...
⾼高并发实时分布式交易易系统实践与思考
萤火虫分布式电源优化,萤火虫优点,C,C++源码 (1).zip
随着电力体制改革的深入推进,分布式电源作为电力市场的一个重要组成部分,其交易模式的研究愈发重要。分布式电源主要指以小规模、分散式的方式存在于用户现场或靠近负荷中心的小型发电系统,它们通常包括太阳能、...
"分布式交易系统架构演进过程" 分布式交易系统架构演进过程是指好买财富基金交易系统从传统金融到互联网金融系统发展历程的演进过程。该架构演进过程包括传统金融系统、分布式交易系统、创新交易系统三个阶段。 ...
北邮 邹华 分布式计算环境第七章——分布式系统设计的几个问题
采用萤火虫算法对分布式电源进行优化,采用33节点系统
基于区块链的分布式能源交易方案设计综述_能源_能源交易_分布式交易_区块链_分布式能源.zip
分布式交易是电力系统领域的一个重要概念,它主要涉及在电力市场中分布式电源(比如家庭太阳能光伏发电系统)与电网公司之间进行电力交易的一种模式。分布式交易允许小型发电站向电网供电,或者直接向附近的消费者...
基于价值认同的需求侧电能共享分布式交易策略matlab源码+项目说明+详细注释.zip基于价值认同的需求侧电能共享分布式交易策略matlab源码+项目说明+详细注释.zip基于价值认同的需求侧电能共享分布式交易策略matlab源码...
基于区块链的分布式能源交易方案设计综述_能源_能源交易_分布式交易_区块链_分布式能源_源码.rar.rar
在给定的文件信息中,我们可以提炼出多个与电力交易、分布式系统、能源管理以及低碳技术相关的知识点。以下是对这些知识点的详细解析: 1. 分布式源荷交易的概念 分布式源荷交易是电力交易的一种形式,它指的是...