当前位置: 首页 > 科技观察

海量数据冷热分离方案与实践

时间:2023-03-16 22:53:58 科技观察

背景随着金融支付业务的快速发展,考虑到未来订单的持续增长,在线存储将面临更大的挑战,因此需要提前规划。目前金融支付主要业务采用mysql(InnoDB)作为数据存储。由于历史订单信息访问频率低,占用数据库存储空间大,希望将历史数据与最新的生产交易数据分开。当前数据库保留最近的时间段。数据作为热存储,历史交易存储在另一个数据库作为冷存储(rocksdb)进行压缩存储,即数据库冷热分离。此举将大大节省数据库设备成本,减少因在线存储空间扩展不足而导致的服务停机时间。以下基于金融支付统一交易系统现状的案例分析,仅供大家参考。方案技术选型架构图方案分析由于业务场景的复杂性,如果按照业务场景来梳理工作量,工作量会呈几何级数增长。在另一个维度上,与数据库相关的操作无非就是查询、插入、更新,只要能够在数据库交互层实现就足以保证查询、插入、更新这些数据库的基本操作会加入冷热分离后不受影响。金融支付代码有统一的层次规范,所有数据库操作都汇聚封装到数据库交互层,更容易改造。在不扩容的情况下,热库预计保留最新X天(时间可调)的数据,X天前的数据在冷库中归档。方案对比方案一:完全可以降低数据库存储压力的方案,但是对冷库的性能要求太高。如果涉及到的插入、更新、查询都可以根据序号过滤时间,就可以减少对冷库的依赖。方案二:适用于性能较低的冷库,涉及到的插入、更新、查询等大部分无法根据订单号进行时间过滤,需要对热库的归档表进行迁移过滤。方案三:如果系统涉及的场景比较简单,历史订单以后不会发生变化,可以按照场景进行归档。方案选择交易:交易表负责记录商户订单与金融支付内部订单的映射、交易金额、买卖双方等重要信息,最重要的功能是防止重复交易。但是,冷库的性能低于热库。商户订单号没有固定规则,无法根据订单号判断时间过滤,降低冷库压力。热存储的cpu使用率很低,热存储数据库的计算不是瓶颈。因此,选择第二个交易选项。交易备案表的主要意义在于减少网上交易对冷库的依赖。支付:支付表负责保存交易订单使用的支付方式、支付方式需要扣除多少、在哪里扣除、从哪里扣除等信息。相关的订单查询、更新、插入可以根据交易订单号或者支付订单号判断时间,减少冷库的查询,所以支付选项一。基本原则为充分保证零事故和零资金损失,在方案设计时提出以下基本原则。在研发、测试、代码审查过程中,参照以下基本原则进行层层把控,可以有效避免生产事故的发生。.数据插入唯一性:热存归档表的所有唯一键必须与待归档的热存表一致。热库存档记录已有的订单,冷库必须有对应的数据。冷库插入:先插入冷库成功,再插入热库归档表。冷库更新:更新冷库数据,使用同一个事务先删除再插入冷库数据。热存删除:删除热存数据时,以冷存数据为where条件,所有热存字段(包括ID)条件都可以删除成功。数据更新一致性:冷库没有更新操作,所有更新操作都必须在热库进行。如果需要更新的数据只存在于冷库中,则需要同步到热库中,然后在热库中完成更新。当冷库和热库数据同时存在时,以热库数据为准。冷库的数据源只是将热库的数据同步到冷库。数据从冷库同步到热库时,归档表和事务表的操作必须在同一个事务内完成,涉及的查询必须使用写库。数据查询的准确性:单次查询:当查询的热库数据不存在时,不需要再次查询冷库(如果订单号可以判断订单日期,可以再加一层日期过滤减少冷库查询)批量查询:冷库和热库数据全部存在时,先返回热库数据。批量查询:合并冷热存储数据后,需要检查是否需要原先查询的接口顺序。如果对顺序有要求,合并后需要排序。降低冷库压力:冷库性能低,在线实时交易最大限度减少对冷库的查询和依赖(可按交易订单号或归档表中的日期过滤)。限制天数控制:数据库交互层天数控制为n,归档任务控制天数为m,要求m>n。比如在模式层,有的判断订单超过n天只会查询冷库,归档任务只归档m天前的历史数据。单独控制可以防止因归档天数的调整而导致数据找不到。具体细节归档表结构归档表状态流一致性删除冷库记录的所有字段作为删除热库的where条件(包括自增id),删除热库和更新热库归档状态为冷库需要在一件事,任何失败时的回滚。交易和支付任务(数据归档、删除、自下而上)归档任务查询热存订单表X(时间可调)天前的订单,将热存订单同步到冷库,插入热存归档表,备案状态为处理中,回车延迟删除mq消息。归档删除TASK常驻服务TASK消费删除mq消息,rpc调用交易支付提供的删除接口,支持本地限流能力。底线任务:主要功能:查询热存归档表中修改时间超过指定时间的订单,并执行强制删除操作。主要用于防止mq异常或日常丢失消息,使用自下而上的任务可以弥补消化过程中的归档记录。执行逻辑数据归档任务(每天一次)for{初始化查询时间范围和分页for{查询X天前的交易订单限制1000(索引排序,滚动时间查询)if记录存在且记录数=1000{forforeachrecord{//开启x个协程处理交易订单,并幂等写入冷库(不保证最新,只保证冷库数据存在)幂等写入归档记录表(类型:PROCESSING,更新为COLD时热存数据被删除,存档记录已经存在,HOT状态更新为PROCESSING)发送MQ延时消息,X分钟后删除热存数据(可配置)}}如果记录数=1000{继续}次rangetomovedown//结束时间超过指定时间则记录不存在{break(跳出循环,任务结束)}redis记录当前查询条件,方便后续任务重新运行重新执行sume}}deletehotstoragedata,consumeMQconsumerMQrecords{querycoldstoragedataconsistencydelete(开启事务条件删除热存储数据,更新归档记录表状态为COLD并结束事务)删除热失败存储一致,将热存数据同步到冷存,一致删除数据}补偿任务(每30分钟启动一次){查询归档记录表状态为PROCESSING,修改时间为X+Y分钟前的记录限制1000ifdoesnotexist{break}for每条记录冷存数据一致性删除(开启事务条件删除热存数据,更新归档记录表状态为COLD并结束事务)Consistent永久删除热存失败存储,将热存数据同步到冷存,一致删除数据}}归档任务查询时间滚动机制:时间范围i的第一个开始时间s为固定日期(财务支付订单的最早日期),结束时间为指定日期,下一个开始时间等于上一个结束时间,结束时间为上一个结束时间加上指定的时间范围)。每次查询下一个时间窗口,redis保存信息,指定日期,当天任务的时间范围,页数。归档任务并发处理:需要支持多任务分片并发处理,增加全天归档订单量:为了不影响在线交易,交易高峰、低峰、每日三个不同时间段24小时区分,归档速度不同。事务-有存档表(查询、添加、更新)特性:唯一键有外部订单号,排序规则是随机的,不能根据订单号判断时间,所以必须有存档表。查询逻辑统一在数据库交互层实现和处理。以下几种情况,可以做特殊处理,减少对数据库冷库的依赖。单号查询:根据外部单号查询,如果查询的qps高,可以先用归档表过滤判断再查询冷库。根据交易订单号查询。如果可以根据订单号判断时间,则在查询冷库前使用订单号过滤时间范围。批量查询:部分功能管理后台功能分页查询,在添加对数据查询范围要求高的冷库查询逻辑时,可以增加传入查询时间范围的起始时间来过滤是否需要查询冷库,对于何时都冷库和热库存在优先保留热库数据(同一页面只过滤相同订单号数据),如对结果有异议,可使用订单号重新查询返回最新重新确认。与产品和运营确认是否支持,只查询热存储。更新逻辑统一在数据库交互层实现,插入逻辑统一在数据库交互层实现。Payment-noarchivetable(query,add,update)特点:唯一键为内部订单号,现有主查询可根据订单号时间判断,无需建表,存储问题热存储数据库可以彻底解决。查询逻辑统一在数据库交互层实现和处理。以下几种情况,可以做特殊处理,减少对数据库冷库的依赖。单条查询:根据付款单号查询。如果可以根据订单号判断时间,则在查询冷库前使用订单号过滤时间范围。批量查询:根据交易订单号查询。如果可以根据订单号判断时间,则在查询冷库前使用订单号过滤时间范围。部分功能管理后台功能分页查询,在添加对数据查询范围要求高的冷库查询逻辑时,可以增加传入查询时间范围的起始时间来过滤是否需要查询冷库,并优先保持热冷库和热库同时存在时的存储数据库数据(同一页面只过滤相同订单号数据),如果对结果有异议,可以使用订单号重新查询,返回最新的重新确认。与产品和运营确认是否支持,只查询热存储。更新逻辑统一在数据库交互层实现,插入逻辑统一在数据库交互层实现。汇总支付彻底解决了由于没有归档表而造成的数据库存储压力问题,大大节省了数据库存储资源。由于为事务增加了归档表,大大延迟了热存数据库的存储压力,为事务数据库提供了额外的缓冲区扩展时间,为事务后续重新优化提供了充足的时间解决数据库存储问题。由此彻底解决了支付数据库的存储压力问题,有效缓解了交易数据库热存储的存储压力。数据库热存储预留天数可灵活调整,可根据后续订单数量合理调整可供存储天数。缺点Transaction采用方案2增加归档表,归档表全量存储数据只能缓解交易和支付数据库存储空间不足的问题,不能彻底解决数据库存储问题。事务表释放的datafree存储空间不能被归档表使用,只能被事务表使用,事务表的datafree空间需要不时释放。