一、什么是最终一致性
在分布式系统中,一致性是指数据在多个副本之间能否保持一致的特性。当系统在数据一致的状态执行更新操作后,也应该保证系统的数据仍保持一致的状态。在CAP理论中,系统的一致性(C),可用性(A),分区容错性(P)不可同时满足,而可用性和分区容错性又是分布式系统必要的,只能牺牲一致性保证系统的最终一致性来保证系统的高可用。
二、传统分布式事务
2PC、3PC协议能保证数据的强一致性,但不是分布式系统中一致性保证的最佳实践。原因如下:
1)分布式系统中各个应用的数据大多是自己私有的,应用之间通过API进行访问,这种方式使得应用之间松耦合,彼此之间很容易进行扩展。若通过传统分布式事务,则将不同应用的数据访问捆绑在一起。
2)不同应用使用不同数据库,若有的应用使用NOSQL数据库,这些非关系型数据库不支持2PC。
三、最终一致性实现
在我原来所做系统中,要根据不同维度记录用户的账本,如根据用户名、银行卡号记录月账、年账。由于数据量大,需对记账数据进行分库分表,一致性的问题就产生了。
采用的方法是创建一张映射表,映射表和请求表一样,通过请求号进行hash取模,因此可保证请求表和映射表在同一个库里,可进行事务操作。映射表中记录的是请求号和每个记账主体的对应关系,当接收到请求时,将请求按记账主体进行拆分后同时入库到请求表和映射表,同时映射表中会记录每个记账主体的状态为记账中(PROCESSING)。
而账本表中则是根据记账主体号进行hash取模,为保证记账操作不重复,增加一张凭证表,凭证表也是根据主体号进行hash取模,且凭证表需保证记账的幂等性。由于凭证表和账本表的入库在一个事务中,可根据是否存在凭证信息来判断记账是否成功。
当记账成功后,回到映射表将对应映射表中的状态改为记账成功(SUCCESS)。同时配置一个定时任务,定期(10分钟)扫描映射表,看是否有状态不为记账成功的记录,若有则重新进行一次记账操作,由于记账时做了幂等性校验,因此重复的记账操作对记账结果没有影响。
还可创建一张重试表,在记账操作重试过若干次(3次)还不成功的情况下,给运营人员发送短信,由人为介入的方式进行相应的调账。至此,可保证记账操作的最终一致性。
本文作者:钟亮(点融黑帮),java程序猿,平常看看电影玩玩游戏,目前就职于点融成都分公司,软件开发工程师一枚。