如何设计一个秒级100万级的订单支付架构

如何设计一个秒级100万级的订单支付架构

在订单支付系统中,往往会面临这样的问题:如何保证每秒万级甚至10万百万级的支付请求或者订单请求。在讲这个这个设计之前来分析下要实现这个秒级100万级的订单支付架构会面临怎样的问题。

1.DB层:读写的压力,高可用,数据库的一致性。

1.1.假定我们使用是的mysql,单库,是无法支撑这个数据量级的并发操作的,我们单库能轻松应对10万级的访问但是绝对支撑不了10万级的写操作。

1.2.假定我们解决了读写的压力问题,我们还将面临高可用的问题,怎样的方案能确保数据库集群宕机后保证数据库的访问不受影响。

1.3.假定我们解决了高可用的问题,我们还需要保证数据库的一致性问题,否则我们将面临数据丢失和不一致的问题。

接下我们将针对上面3个问题来逐步分析:

1.1.数据库的读写问题,这是这个架构设计里面最重要最核心的问题。我们知道,通常解决读写问题是通过分库分表来解决的。分库分表可以把执行sql的压力根据既定的规则分摊到不同的库和表,从而减小数据库的压力。不论是是分库还是分表都是为了减小sql执行等待的时间。接下来开始我关于分库分表的设计,以订单表的设计为例:我们很清楚的知道分库分表要解决的问题是订单表的id主键设计问题,要保证在所有库和表中是唯一的。怎么保证呢,唯一性很容易想到UUID,UUID确实可以保证全局唯一,不过UUID存在两个问题:UUID一段随机的字符串是没有顺序的,执行查询的效率是很低的;UUID是没有业务含义的不具备业务含义的区分。

设计:我们已用的ID来做键值的区分依据,采用二叉树的方式来分库分表。我们假设我们把order分成16个库,每个库里面有10张表,这样我们就有160张表分布在16个库里面。

在这里插入图片描述
接下来最关键的就是通过用户ID(UID)来计算和分配落地到哪个库的哪张表。

算法:我这边库的设计都是按8的倍数来设计的,便于后面做扩容的时候以8的倍数来扩容,算法能完美适用扩容。

假设用户的ID为765

数据库编号=(((765/10)% 16+1)-1)%8-1 下取整 ====》 DB5

表序号=(765)%10 下取整 order5

通过这样的计算我们可以把任何一个用户均匀的分配到各个数据库和表。

这一步完成之后,我们还需要做的就是我们的程序如何按照这个算法实现了,我这边用的设计是在我们的应用程序计算处出用户的这个订单该落在哪个库哪个表。

有了分库分表的计算落地方案后,接下来我们来设计下订单ID:刚刚提到了UUID的不足之处,所以不能使用UUID;因为是分库分表所以表的ID自增是不可行的。这边我采用了现在的雪花算法(是有序的),雪花算法计算的ID是毫秒级的,1秒能产生26万的唯一值。显然能满足10级的使用。我在雪花的基础上在订单Id的上还增加了库表的信息。

订单ID=分库分表信息+雪花ID(机器编号+集群编号+时间戳+自增ID)

这样我们基本上解决了分库和分表的问题,同时有了高效的订单编号计算的方案和算法。

1.2 接下来我们来探讨下 关于高可用的问题,如果我们所有的库表都放在一台机器上,一旦服务器宕机,那后果将是灾难性的。所以高可用的方案是保证服务稳定运行的必要条件。如何高可用呢,我们首先想到的是数据库的集群和主从备份。主从同步可以把主库的数据实时同步到从库,在这个过程中我们还可以实现读写分离,主库写,从库读等操作。

在这里插入图片描述
1.3.数据的一致性:在整个设计过程我们已经考虑了分库分表的落地设计解决了读写并发的问题,通过数据库的集群和主从设计实现了数据库的高可用。还有一个问题至关重要,就是数据的一致性,通常在订单支付的系统中,我们会按用户来切分数据库的集群比如C端用户和B端商户,那么数据的一致性就需要得到保证,在设计过程中我们可以选用消息中间件来保证数据的写入,在通过数据库的监听中间件来同步不同集群的差异数据。

2.对数据等级的分类:在设计这种高并发海量数据的系统,我们往往会通过各种缓存机制比如redi等来提供系统的访问速度和性能。那么是不是所有表的数据我们都能做缓存呢?答案是肯定不行的,所以我们需要对我们系统里表的数据等级做划分,哪些是可以缓存的,哪些是不可以做缓存的。这边有参考乐视支付系统架构的设计,把数据分成几种等级:

第1级:订单数据和支付流水数据;这两块数据对实时性和精确性要求很高,所以不添加任何缓存,读写操作将直接操作数据库。

第2级:用户相关数据;这些数据和用户相关,具有读多写少的特征,所以我们使用redis进行缓存。

第3级:支付配置信息;这些数据和用户无关,具有数据量小,频繁读,几乎不修改的特征,所以我们使用本地内存进行缓存。

按照这样的等级划分,我们就能很清晰的分配资源和设计缓存,同时不会影响业务又能提供系统的性能。

3.在分析完DB这一侧的分析后我们来分析下,数据流量的问题:我们先来分析一个关于秒杀活动的问题,假设我们的库存有100件商品,但是参与活动的人可能有10万甚至更多。这个时候我们如果有10万个请求并发访问,毫无疑问系统数据库100%炸,导致的后果很可能一件商品没被购买,系统还崩了。大多数的秒杀活动实际上真正到db层或者应用层的请求很可能才100,其余的请求被随机丢弃了,这样就能很好的保证系统的正常运行,同时秒杀本身就存在抢不到的情况,所以没抢到的用户也只会认为是自己的手速或者网络问题。其实这是一钟很好的思路,既没有过度去想技术实现(成本很高,实现很复杂),又很好的完成了业务诉求。实际上我们所谓的订单支付限流也可以借鉴这种思想,不过在丢弃请求这个细节是不同的,你不能把用户的支付请求丢弃掉;所以怎么做呢?我们借鉴秒杀的思想,我们在每秒最大能到DB层的请求(R)要做个设计,R<MAX(DB我们设计支持最大的并发数)*80%,如何保证R的值呢,因为用户的请求是不可控的(当然是越多越好), 这个时候我们在用户的请求过来前要做一层拦截,可以通过nginx来做流量控制,也可以通过消息队列来接收请求,让多余的请求排队,始终保持R满足前面提到的值要求。这样既能充分利用系统设计的性能,又能避免系统过载,导致严重的后果。
在这里插入图片描述
总结:这边的设计主要是从数据库DB层面和请求流量两个方面阐述设计思路,实际应用钟,在代码层面还有很多很多的细节要考虑,比如分布式事务,缓存更新同步策略,数据计算,多表操作等等。这边分享的主要还是以思想为主, 大家又兴趣可以尝试自己搭建,模拟大请求尝试一下,体会会更深,好的设计一定是为业务服务的,既不要过度设计(秒杀)也不要考虑的很不周全,导致后续扩展的问题。好的架构—》简单,适用,可演变 我坚信的架构理念。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值