互联网行业是大势所趋,从招聘工资水平即可看出,那么如何提升自我技能,满足互联网行业技能要求?需要以目标为导向,进行技能提升,本文主要针对招聘中高频提及的分布式系统设计、架构(数据一致性)做了分析,祝各位早日走上属于自己的"成金之路"。
 
目录:
问题分析
概念解读
Most Simple原理解读
eBey、去哪儿、蘑菇街分布式事务案例分析
参考资料

1.问题解析    
要想做架构,必须识别出问题,即是谁的问题,什么问题。
明显的,分布式架构解决的是高并发的问题,高并发下服务高可用和数据一致性问题问题;当规模规模较小时,单库HA即可满足请求,当业务规模持续增加,单库已经无法满足业务需求,业界主流做法,是对业务进行分表、分库,那么原来的有些业务,现在则要在一个事务中,保证两个库同时操作成功或操作不成功(一个库成功,一个库失败,要么重新尝试失败库操作直到成功,要么回滚成功库)。随之而来的问题既是如何保证分库时业务操作的数据一致性。理解分布式架构、分布式系统数据一致性的问题、起源是第一步。
这里多啰嗦一点,分库后,每个库可以采取不同的语言,以时下很流行的微服务向外提供服务;但是业务量不大的情况下,使用微服务到增加了复杂性及技术成本。明白技术的起源,针对不同的业务量,采取适当的架构、以最恰当的方式承载业务,是架构师必须具备的能力。
 
2.常见概念解读:
a.关系型数据库通常具有ACID特性:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。
b.Base(basically available, soft state, eventually consistent):一种 Acid 的替代方案,BASE 的可用性是通过支持局部故障而不是系统全局故障来实现的。化学理论中ACID是酸、Base恰好是碱。
c.CAP定律:在分布式系统中,同时满足"CAP定律"中的"一致性"、"可用性"和"分区容错性"三者是不可能的。
d.强一致:当更新操作完成之后,任何多个后续进程或者线程的访问都会返回最新的更新过的值。这种是对用户最友好的,就是用户上一次写什么,下一次就保证能读到什么。根据 CAP 理论,这种实现需要牺牲可用性,常见的RDBMS。
e.弱一致性:系统并不保证续进程或者线程的访问都会返回最新的更新过的值。系统在数据写入成功之后,不承诺立即可以读到最新写入的值,也不会具体的承诺多久之后可以读到。
f.最终一致性:弱一致性的特定形式。系统保证在没有后续更新的前提下,系统最终返回上一次更新操作的值。在没有故障发生的前提下,不一致窗口的时间主要受通信延迟,系统负载和复制副本的个数影响。DNS 是一个典型的最终一致性系统。
为保证可用性,互联网分布式架构将强一致性需求转换成最终一致性的需求,并通过系统执行幂等性的保证,保证数据的最终一致性。
 
幂等性(Idempotence):分布式架构的基石,即同一个操作无论请求多少次,其结果都相同。
典型的是HTTP,Methods can also have the property of "idempotence" in that (aside from error or expiration issues) the side-effects of N > 0 identical requests is the same as for a single request.
 
每个概念实际所解决的是人遇到的某个特定的问题,发现其背后所代表的问题,是理解分布式架构、分布式系统数据一致性第二步。
 
3.Most Simple原理解读
假设有一个从账户取钱的远程API(可以是HTTP的,也可以不是),我们暂时用类函数的方式记为:

bool withdraw(account_id, amount)
withdraw的语义是从account_id对应的账户中扣除amount数额的钱;如果扣除成功则返回true,账户余额减少amount;如果扣除失败则返回false,账户余额不变。
值得注意的是:和本地环境相比,我们不能轻易假设环境的可靠性
一种典型的场景是withdraw请求已经被服务器端正确处理,但服务器端的返回结果由于网络等原因被掉丢了,导致客户端无法得知处理结果。如果是在网页上,一些不恰当的设计可能会使用户认为上一次操作失败了,然后刷新页面,这就导致了withdraw被调用两次,账户也被多扣了一次钱。如图1所示:



一种更轻量级的解决方案是幂等设计。我们可以通过一些技巧把withdraw变成幂等的,比如:

int create_ticket() 
bool idempotent_withdraw(ticket_id, account_id, amount)
create_ticket的语义是获取一个服务器端生成的唯一的处理号ticket_id,它将用于标识后续的操作。idempotent_withdraw和withdraw的区别在于关联了一个ticket_id,一个ticket_id表示的操作至多只会被处理一次,每次调用都将返回第一次调用时的处理结果。这样,idempotent_withdraw就符合幂等性了,客户端就可以放心地多次调用。

基于幂等性的解决方案中一个完整的取钱流程被分解成了两个步骤:1.调用create_ticket()获取ticket_id;2.调用idempotent_withdraw(ticket_id, account_id, amount)。虽然create_ticket不是幂等的,但在这种设计下,它对系统状态的影响可以忽略,加上idempotent_withdraw是幂等的,所以任何一步由于网络等原因失败或超时,客户端都可以重试,直到获得结果。如图所示:



和分布式事务相比,幂等设计的优势在于它的轻量级,容易适应异构环境,以及性能和可用性方面。在某些性能要求比较高的应用,幂等设计往往是唯一的选择。
 
幂等性是分布式架构、分布式系统数据一致性的底层基本原理,理解这一步,是走上"成金之路"的关键。
 
4.案例分析
a.eBay经典的BASE模式
一个最常见的场景,如果产生了一笔交易,需要在交易表增加记录,同时还要修改用户表的金额。这两个表属于不同的库及远程服务,所以就涉及到分布式事务一致性的问题。
 
核心思想是用两个事务来保证一致性,同时用异步保证了可用性:一个事务处理主要操作"增加交易表记录"与异步消息构建,另外一个事务用来处理构建的异步消息;第一个事务即处理主要业务又记录次要业务,同时还能快速返回,保证了高可用性,第二个事务则用来保证数据的一致性。(即将buyer和seller表更新的处理转为"线下"处理,消息日志可以存储到本地文本、数据库或消息队列,再通过业务规则自动或人工发起重试。人工重试更多的是应用于支付场景,通过对账系统对事后问题的处理,类似与淘宝双11重复支付后续退款)
 
一个经典的解决方法,将主要修改操作以及更新用户表的"异步消息"放在一个本地事务来完成。同时为了达到多次重试的幂等性,避免重复消费用户表消息带来的问题,增加一个更新记录表 updates_applied 来记录已经处理过的消息。
在第一事务中,通过本地的数据库的事务保障,保证"增加交易表记录"、"增加两条异步消息队列记录(一条处理buyer表、一条处理seller表)",同时成功或同时失败。
在第二事务中,分别读出消息队列(但不删除),通过判断更新记录表 updates_applied 来检测相关消息是否被执行,如没执行,则执行相关业务逻辑(保证幂等性,保证即使执行过程中异常,重复执行没有任何问题),执行完所有消息后然后增加一条操作记录到updates_applied,事务到此结束。用事务保证两个异步消息执行及updates_applied的一致性操作(又称为分布式事务框架)。最后删除队列。
 
b.去哪儿网分布式事务方案
i.优先使用异步方案,原理和"a.eBay经典的BASE模式"类似,对业务逻辑处理不能保证"幂等性"的,增加去重表(即a中的updates_applied) 来处理
ii.对于不适合异步消息处理的业务,如A、B、C三方需要同步处理才能返回:在A、B、C三个库中分别维护一个事务记录表recorda/recordb/recordc,当A、B、C业务事务处理完,将结果存到对应的recordx中,由一个中心服务对比查询三方的事物记录表,有如下两种处理方式:
    第一种:A、B成功,C失败了,重试C,知道C成功;
    第二种:C不可能成功时,回滚A、B,如C为扣库存,当库存为0时,则不能成功(不考虑补库存)。
另,这种recordx表由RPC框架层进行维护,对业务是透明的。
 
c.蘑菇街交易创建过程
场景:将下单功能拆分为12个子业务(见参考资料b),对于非实时、非强一致性的关联业务,使用"eBay经典的BASE模式"思想,第一个本地事务执行成功后,以发消息通知、关联事务异步化执行方案,来避免a中第二个事务的"分布式事务框架"对业务带来的侵入和复杂性,具体方案是基于DB事件变化通知给MQ,而MQ消费者通过ACK,保证消息一定消费成功,完成强一致性(消息可能会被重发,所以消息消费方要保证幂等性)。
 
而对要求同步做、强一致性要求的场景(和b的ii相同场景),如优惠券和优惠券减库存:可以引入"a.eBay经典的BASE模式"的第二个事务(分布式事务框架)来处理,但是复杂性会急剧上升;
另一种方式是创建一个不可见订单,然后在同步调用锁券和扣减库存时,针对调用异常(失败或者超时),发出废单消息到MQ。如果消息发送失败,本地会做时间阶梯式的异步重试;优惠券系统和库存系统收到消息后,会进行判断是否需要做业务回滚,这样就准实时地保证了多个本地事务的最终一致性。
根据业务进行不同的方案处理,解决了分布式架构、分布式系统的数据一致性问题。
 

整体来说,蘑菇街的案例可迁移性强,可移植性好,可以尝试模拟下实际场景,驾驭分布式架构、分布式系统数据一致性方案,祝大家早日走上"成金之路",看到这里,烦请不吝"推荐",谢谢!
 
5.参考资料:
 

不懂这些分布式架构、分布式系统的数据一致性解决方案,你如何能找到高新互联网工作呢?强势解析eBay BASE模式、去哪儿及蘑菇街分布式架构的更多相关文章

  1. 不懂这些高并发分布式架构、分布式系统的数据一致性解决方案,你如何能找到高新互联网工作呢?强势解析eBay BASE模式、去哪儿及蘑菇街分布式架构

    互联网行业是大势所趋,从招聘工资水平即可看出,那么如何提升自我技能,满足互联网行业技能要求?需要以目标为导向,进行技能提升,本文主要针对高并发分布式系统设计.架构(数据一致性)做了分析,祝各位早日走上 ...

  2. 强势解析eBay BASE模式、去哪儿及蘑菇街分布式架构

    互联网行业是大势所趋,从招聘工资水平即可看出,那么如何提升自我技能,满足互联网行业技能要求?需要以目标为导向,进行技能提升,本文主要针对高并发分布式系统设计.架构(数据一致性)做了分析,祝各位早日走上 ...

  3. 解析eBay BASE模式、去哪儿及蘑菇街分布式架构

    目录:问题分析概念解读Most Simple原理解读eBey.去哪儿.蘑菇街分布式事务案例分析 参考资料 1.问题解析    要想做架构,必须识别出问题,即是谁的问题,什么问题.明显的,分布式架构解决 ...

  4. Re:从 0 开始的微服务架构--(四)如何保障微服务架构下的数据一致性--转

    原文地址:http://mp.weixin.qq.com/s/eXvoJew3bjFKzLLJpS0Otg 随着微服务架构的推广,越来越多的公司采用微服务架构来构建自己的业务平台.就像前边的文章说的, ...

  5. RDS 5.7三节点企业版时代的数据一致性解决方案

    上篇我们看到了在MySQL主备模式下,我们在数据一致性上做了不少事情,但解决方案都有一定的局限性,适合部分场景或者解决不彻底的问题.随着以Google Spanner以及Amazon Aruora 为 ...

  6. Redis与DB的数据一致性解决方案(史上最全)

    文章很长,而且持续更新,建议收藏起来,慢慢读! 高并发 发烧友社群:疯狂创客圈(总入口) 奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : 极致经典 + 社群大片好评 < Java 高并发 三 ...

  7. MySQL主备模式的数据一致性解决方案

     根据阿里交易型业务的特点,以及在双十一这样业内罕有的需求推动下,我们在官方的MySQL基础上增加了非常多实用的功能.性能补丁.而在使用MySQL的过程中,数据一致性是绕不开的话题之一.本文主要从阿里 ...

  8. C# .Net 多进程同步 通信 共享内存 内存映射文件 Memory Mapped 转 VC中进程与进程之间共享内存 .net环境下跨进程、高频率读写数据 使用C#开发Android应用之WebApp 分布式事务之消息补偿解决方案

    C# .Net 多进程同步 通信 共享内存 内存映射文件 Memory Mapped 转 节点通信存在两种模型:共享内存(Shared memory)和消息传递(Messages passing). ...

  9. redis系列之数据库与缓存数据一致性解决方案

    redis系列之数据库与缓存数据一致性解决方案 数据库与缓存读写模式策略 写完数据库后是否需要马上更新缓存还是直接删除缓存? (1).如果写数据库的值与更新到缓存值是一样的,不需要经过任何的计算,可以 ...

随机推荐

  1. 统计SQLSERVER表行数,以及每天数据变化的行数

    此sql对监控系统很有帮助,知道哪些表压力大,每天的数量级大概多少等信息. 得到这些信息就可以做相应的策略来进行系统优化. create table tmp( name varchar(50), ro ...

  2. 关于pandas精度控制

    最近使用pandas处理一批数据,数据中包含几个columns,它们的数据精度,例如 3.25165,1451684684168.0,0.23 处理完之后保存csv时发现,1451684684168. ...

  3. 浅谈Socket长连+多线程[原创,欢迎指点]

    前戏 [PS:原文手打,转载说明出处] [PS:博主自认为适用于云平台设备管控,且适用于IM主控] 好久没来了,13年时还想着多写一些博客,这都17年过年,年前也写一写Scoket+多线程,不足之处, ...

  4. CodeForces 327C

    Magic Five Time Limit:1000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit  ...

  5. 微信小程序维护登录态与获取用户信息

    前言. 微信小程序的运行环境不是在浏览器下运行的.所以不能以cookie来维护登录态.下面我就来说说我根据官方给出的方法来写出的维护登录态的方法吧. 一.登录态维护 官方的文档地址:https://m ...

  6. 《JAVASCRIPT高级程序设计》创建对象的七种模式

    细看javascript创建对象模式的诞生,具体的脉络为:不使用任何模式——工厂模式——构造函数模式——原型模式——组合使用构造函数模式——动态原型模式——寄生构造函数模式——稳妥构造函数模式.每一种 ...

  7. W3Cschool学习笔记——HTML基础教程

    什么是 HTML? HTML 是用来描述网页的一种语言. HTML 指的是超文本标记语言 (Hyper Text Markup Language) HTML 不是一种编程语言,而是一种标记语言 (ma ...

  8. npm 不是内部命令

    最近办公室流行给电脑装win10系统,于是在重新装好电脑系统后,再次运行thinkjs项目的时候,就发现了之前做过的项目打不开了,待再确认问题出在哪里的时候,才发现”nodejs以及npm不是内部或者 ...

  9. 【2(2N+1)魔方阵 】

    /* 2(2N+1)魔方阵 */ #include<stdio.h> #include<stdlib.h> #define N 6 #define SWAP(x, y) {in ...

  10. Linux驱动技术(八) _并发控制技术

    为了实现对临界资源的有效管理,应用层的程序有原子变量,条件变量,信号量来控制并发,同样的问题也存在与驱动开发中,比如一个驱动同时被多个应用层程序调用,此时驱动中的全局变量会同时属于多个应用层进程的进程 ...