2023-04-23 19:33:26
转账业务实现最终一致性的六个阶段如下:
阶段一:SELECT & UPDATE
操作方式:先通过SELECT查询账户余额,判断余额是否充足,再进行UPDATE操作更新余额。
特点:需要很强的数据库隔离级别来保证操作的原子性,防止在查询和更新之间出现并发问题。
缺点:在高并发场景下,单纯的SELECT & UPDATE可能导致数据不一致。
阶段二:UPDATE WHERE
操作方式:在UPDATE语句中添加WHERE条件,直接判断余额是否充足,如UPDATE account SET amount=amount+:delta WHERE account_id=:account_id AND amount+:delta > 0。
特点:仅依赖SQL的单条事务,简化了操作流程。
缺点:不支持幂等操作,即无法防止重复转账导致的余额错误。
阶段三:INSERT EVENT & UPDATE
操作方式:在更新账户余额的同时,插入一条转账事件记录。利用数据库主键不重复的特性,确保转账操作的幂等性。
特点:通过数据库事务保证INSERT EVENT和UPDATE的同时成功或失败。
缺点:要求收款方和付款方的账户必须在同一个数据库实例上,限制了系统的扩展性。
阶段四:分拆成两个独立的事务
操作方式:将转账操作拆分为两个独立的数据库事务,分别处理扣款和加款。由应用层来保证数据的最终一致性。
特点:当返回结果为unknown时,表示系统数据处于不一致状态,需要通过重试机制来恢复数据一致性。
缺点:自动重试功能未实现,需考虑使用延迟任务等方式实现重试。
阶段五:两阶段提交
操作方式:引入冻结账户的概念,将转账过程分为多个步骤,每个步骤都有对应的回滚操作。通过两阶段提交确保转账的原子性。
特点:避免了事务处理过程中的钱被其他事务使用掉的问题,提高了系统的稳定性。
缺点:实现复杂,需要处理多种异常情况,如回滚失败等。
阶段六:热点账户处理
操作方式:对于交易特别频繁的热点账户,将余额和流水记录到多个子账户下。通过分散锁竞争来提高系统的并发性能。
特点:先查询子账户余额并计算转账计划,然后执行转账计划。如果失败则重新查询并计算新的转账计划。
缺点:增加了系统的复杂性,需要处理子账户之间的余额分配和转账计划的计算问题。