浅谈支付业务的分表方案

浅谈支付业务的分表方案_第1张图片

        在互联网相关的业务场景中,为了解决数据存储层面的扩展问题,满足线上的并发性能需求,经常会对数据库(如mysql)进行分库分表操作。常见的分表方案都是基于水平拆分,如基于range分段拆分,或者基于hash取模的方式等等。实际上,分表的规则的设计往往是基于实际业务场景来决定的,此外还要事先对系统的规模进行数据推演等等,如短期内是否会出现爆发式的业务增长,这些都是决定系统架构设计是否成熟的关键因素。下面分享一个实际案例。

        在电商平台的支付系统中,核心的一个数据模型就是支付快照(也叫支付流水),一个中小型的电商平台,线上线下业务都包含在内,日支付流水大概在20w笔左右,系统设计初期,由于团队内部人员大家都没有分库分表这方面的经验,心态上也是不敢越雷池半步这种,领导拍板决定:“听我的,先这么做!”,保守做法就是先按单表设计(由于大家都没有数据推演的意识),为了避免过度设计,先简单实现。

        ps:这里插一句,个人感悟,在架构设计中,其实“过度设计”和“合理设计”的定论,大都是经过实践验证之后得出来的!也很难区分边界。

        就这样,经过一个月得开发,系统终于上线了,也迎来了第一笔支付流水!初期得时候,业务量没上来,单日数据增量也就在1-2w条左右,随着业务得推广,3个月后,业务量上来了,单日数据增量达到了20w+,眼看着快照表的数据量直线上涨(此时领导仍然没有意识的危机所在),不久,单表数据量就达到了2kw左右。但由于查询sql较为简单,索引设计的也比较合理等,性能上还没到瓶颈。

        ps:补充一下表结构的设计,整张表大概有13到15个字段左右,包含一个扩展字段(冗余,存储json串),大部分数据类型都是数字类型,索引有3个,查询全部走索引,高峰期,每秒查询能达到几百次左右。

        又过了几个月后,单表的数据量达到了5kw左右,偶发的会出现慢查询等问题了,偶尔也会出现主从延迟等等。这个时候领导开始关注这个问题了!!!

        在支付快照的数据查询逻辑中,实时查询方面,主要场景是查询“近期”的数据,比如用于防止重复支付等等,以及相关幂等操作等等,或者是在退款业务中会设计到查询快照,经过数据分析我们发现一年以上的支付单退款的概率几乎为0,半年以上的支付单退款数量也是寥寥无几,所以总结规律就是快照表的实时查询都是集中在半年以内的数据上,95%的查询都是集中在1周以内。其他的数据查询场景,对时效性要求不高的就是一些报表统计之类的业务都是在每天的低峰期邮定时任务离线生成。

        总结完数据的查询规律后,我们发现快照数据举有明显的“冷热数据之分”,因此并不适合做水平拆分,应该考虑一种按照数据的冷热特性来进行分表的方案。

        ps:任何架构设计都有它照顾不到的地方,没有万能的设计,往往都要进行取舍,只要能解决你的痛点,并能覆盖到绝大多数场景,那这个架构设计就是成功的!

        我们先看一下大致的方案是什么样的:

浅谈支付业务的分表方案_第2张图片

        我们可以把数据拆分成冷数据和热数据,热数据满足线上99%的实时查询需求,冷数据用于做归档和离线统计分析。冷数据按照时间进行分表存储(或者考虑可靠的分布式存储),如按年或者按季度都可以,具体拆分粒度根据业务量决定。此时有人会问,如果恰好有少量的查询在热库中查不到怎么办?如半年以前的单子要进行退款。对于这个问题,我觉得可以有一下几种方案:

        1、在查询的业务层进行关联映射,如果在热库中查不到时,在去冷库中进行查询。此时查询性能上肯定会有一些损耗,但是偶尔少量的查询,慢一点又怎么样的?

        2、业务层面进行约定,如仅允许半年以内的订单进行退款等等(实际可能不一定合理,还是看业务需求来定)。

        这样就可以满足大部分业务场景了。至于方案的具体细节,就不一一赘述了,如分布式发号器的实现,可以参考博主的另外一篇博文https://blog.csdn.net/u012737673/article/details/89240144,分享了实现还有源码可以下载参考。做为一个程序员,其实架构设计离我们并不远,任何方案也不是生搬硬套的,都是基于自己业务场景做加法和减法得来的。遇到困难,先在战略上藐视它,提升自信心,多重视细节,才能做出好的设计!

        本人不才,才疏学浅,这是本人第一篇谈架构设计的文章,感兴趣的朋友多多关注支持,一起进步。大佬出门请左转,不喜勿喷!

你可能感兴趣的:(架构设计,mysql,java,后端,分库分表,架构设计)