分布式系统下数据一致性
通常情况下业务都是由简至繁,导致系统也会由单个拆分成多个独立的服务,从而带来分布式环境下数据一致性问题。
业务场景:比如有一个业务操作,同时调用服务A、B、C,需要满足要么同时成功,要么同时失败。A、B、C服务分别由不同部门开发,不同数据库存储,同时部署在不同远程服务器上。
在分布式系统中,如果不想牺牲一致性,CAP理论告诉我们最多实现其中2点,因为需要牺牲可用性,这显然是不能接受的。下面先简单介绍下数据一致性基础理论。
强一致性
当更新完成之后,任何多个后续进程或者线程的访问都会返回最新的更新过的值。这种是对用户最友好的。
弱一致性
系统并不保证后续进程或线程的访问都会返回最新更新过的值。系统在数据写入成功之后,不承诺立即可以读到最新写入的值,也不会具体的承诺多久之后可以读到。
最终一致性
弱一致性的特定形式。系统在保证没有后续更新的情况下,系统最终返回上一次更新的值。在没有故障发生的前提下,不一致
在实践上,为了保障系统的可用性,大多会将强一致性需求转化为最终一致性,并通过系统执行幂等性的保证,保证数据最终一致性。下面分享下一些解决方案 。
1.规避分布式业务——业务整合
业务整合方案主要采用将接口整合到本地执行的方法。比如可以将服务A、B、C整合为一个服务D给业务,服务D再通过转换为本地事务的方式。
优点:规避了分布式事务。缺点:把本来拆分好的业务又耦合到一起,业务职责不清晰,不利于维护。
2.消息日志的方式
此方案的核心是将需要分布式处理的任务通过消息日志的方式来异步执行。消息日志可以存储到本地文本、数据库或消息队列,再通过业务规则自动或人工发起重试。人工重试更多的是应用于支付场景,通过对账系统对事后问题的处理。
消息日志方案的核心是保证服务接口的幂等性。
考虑到网络通讯失败,数据丢包等问题,如果服务接口不能保证幂等行,数据唯一性将很难得到保证。
BASE(basically available, soft state, eventually consistent):一种ACID的替代方案。
BASE的可用性是通过支持局部故障而不是全局故障来实现的。如果将分区在5个数据库服务器上,BASE设计鼓励类似的处理方式,一个用户数据库的故障只影响这台特定主机那20%的用户。
一个最常见的场景,如果发生一笔交易,需要在交易表中增加记录,同时还要修改用户表的金额。这两个表属于不同的远程服务,所以就涉及到分布式事务一致性问题。
一个不错的解决方法,将主要修改操作以及更新用户表消息放在一个本地事务中来完成。同时为了避免重复消费用户表消息带来的问题,达到多次重试的幂等性,增加一个更新记录表track_msg来记录已经处理过的消息。
基于上面讲的,在第一阶段,通过本地的数据库的事务保障,增加了transaction表及消息队列。
在第二阶段,分别读出消息队列,通过判断更新记录表track_msg来检测相关记录是否被执行,未被执行的记录会修改user表信息,然后增加一条记录到track_msg,事务执行成功后再删除队列,从而达到分布式数据最终一致性。
尽量将分布式事务转换为多个本地事务,通过消息、重试等方式达到最终一致性。
分布式服务对衍生的配套系统要求比较多,特别是我们基于消息、日志的最终一致性方案,需要考虑消息的积压、消费情况、监控、报警等。
转载于:https://my.oschina.net/nbspjj/blog/738285