标签 分布式 下的文章 - 第 3 页 - 酷游博客
首页
关于
友链
Search
1
阿里的简历多久可以投递一次?次数多了有没有影响?可以同时进行吗?
45 阅读
2
Java中泛型的理解
40 阅读
3
Java 14 发布了,再也不怕 NullPointerException 了!
38 阅读
4
Java中的可变参数
37 阅读
5
该如何创建字符串,使用" "还是构造函数?
29 阅读
技术
登录
/
注册
找到
16
篇与
分布式
相关的结果
- 第 3 页
2025-01-22
Java中的事务——JDBC事务和JTA事务
我的博客中曾经关于事务有过很多讨论,之前的事务介绍基本都是数据库层面的事务,本文来介绍一下J2EE中和事务相关的内容,在阅读本文之前,希望读者对分布式有一定的了解。 关于事务的基础知识这里不再详细介绍,想要了解的同学可以在我的博客中阅读相关文章。 Java事务的类型有三种:JDBC事务、JTA(Java Transaction API)事务、容器事务。 常见的容器事务如Spring事务,容器事务主要是J2EE应用服务器提供的,容器事务大多是基于JTA完成,这是一个基于JNDI的,相当复杂的API实现。所以本文暂不讨论容器事务。本文主要介绍J2EE开发中两个比较基本的事务:JDBC事务和JTA事务。 JDBC事务 JDBC的一切行为包括事务是基于一个Connection的,在JDBC中是通过Connection对象进行事务管理。在JDBC中,常用的和事务相关的方法是: setAutoCommit、commit、rollback等。 下面看一个简单的JDBC事务代码: public void JdbcTransfer() { java.sql.Connection conn = null; try{ conn = conn =DriverManager.getConnection("jdbc:oracle:thin:@host:1521:SID","username","userpwd"); // 将自动提交设置为 false, //若设置为 true 则数据库将会把每一次数据更新认定为一个事务并自动提交 conn.setAutoCommit(false); stmt = conn.createStatement(); // 将 A 账户中的金额减少 500 stmt.execute("\ update t_account set amount = amount - 500 where account_id = 'A'"); // 将 B 账户中的金额增加 500 stmt.execute("\ update t_account set amount = amount + 500 where account_id = 'B'"); // 提交事务 conn.commit(); // 事务提交:转账的两步操作同时成功 } catch(SQLException sqle){ try{ // 发生异常,回滚在本事务中的操做 conn.rollback(); // 事务回滚:转账的两步操作完全撤销 stmt.close(); conn.close(); }catch(Exception ignore){ } sqle.printStackTrace(); } } 上面的代码实现了一个简单的转账功能,通过事务来控制转账操作,要么都提交,要么都回滚。 JDBC事务的优缺点 JDBC为使用Java进行数据库的事务操作提供了最基本的支持。通过JDBC事务,我们可以将多个SQL语句放到同一个事务中,保证其ACID特性。JDBC事务的主要优点就是API比较简单,可以实现最基本的事务操作,性能也相对较好。 但是,JDBC事务有一个局限:一个 JDBC 事务不能跨越多个数据库!!!所以,如果涉及到多数据库的操作或者分布式场景,JDBC事务就无能为力了。 JTA事务 为什么需要JTA 通常,JDBC事务就可以解决数据的一致性等问题,鉴于他用法相对简单,所以很多人关于Java中的事务只知道有JDBC事务,或者有人知道框架中的事务(比如Hibernate、Spring)等。但是,由于JDBC无法实现分布式事务,而如今的分布式场景越来越多,所以,JTA事务就应运而生。 如果,你在工作中没有遇到JDBC事务无法解决的场景,那么只能说你做的项目还都太小。拿电商网站来说,我们一般把一个电商网站横向拆分成商品模块、订单模块、购物车模块、消息模块、支付模块等。然后我们把不同的模块部署到不同的机器上,各个模块之间通过远程服务调用(RPC)等方式进行通信。以一个分布式的系统对外提供服务。 一个支付流程就要和多个模块进行交互,每个模块都部署在不同的机器中,并且每个模块操作的数据库都不一致,这时候就无法使用JDBC来管理事务。我们看一段代码: /** 支付订单处理 **/ @Transactional(rollbackFor = Exception.class) public void completeOrder() { orderDao.update(); // 订单服务本地更新订单状态 accountService.update(); // 调用资金账户服务给资金帐户加款 pointService.update(); // 调用积分服务给积分帐户增加积分 accountingService.insert(); // 调用会计服务向会计系统写入会计原始凭证 merchantNotifyService.notify(); // 调用商户通知服务向商户发送支付结果通知 } 上面的代码是一个简单的支付流程的操作,其中调用了五个服务,这五个服务都通过RPC的方式调用,请问使用JDBC如何保证事务一致性?我在方法中增加了@Transactional注解,但是由于采用调用了分布式服务,该事务并不能达到ACID的效果。 JTA事务比JDBC事务更强大。一个JTA事务可以有多个参与者,而一个JDBC事务则被限定在一个单一的数据库连接。下列任一个Java平台的组件都可以参与到一个JTA事务中:JDBC连接、JDO PersistenceManager 对象、JMS 队列、JMS 主题、企业JavaBeans(EJB)、一个用J2EE Connector Architecture 规范编译的资源分配器。 JTA的定义 Java事务API(Java Transaction API,简称JTA ) 是一个Java企业版 的应用程序接口,在Java环境中,允许完成跨越多个XA资源的分布式事务。 JTA和它的同胞Java事务服务(JTS;Java TransactionService),为J2EE平台提供了分布式事务服务。不过JTA只是提供了一个接口,并没有提供具体的实现,而是由j2ee服务器提供商 根据JTS规范提供的,常见的JTA实现有以下几种: 1.J2EE容器所提供的JTA实现(JBoss) 2.独立的JTA实现:如JOTM,Atomikos.这些实现可以应用在那些不使用J2EE应用服务器的环境里用以提供分布事事务保证。如Tomcat,Jetty以及普通的java应用。 JTA里面提供了 java.transaction.UserTransaction ,里面定义了下面几个方法 begin:开启一个事务 commit:提交当前事务 rollback:回滚当前事务 setRollbackOnly:把当前事务标记为回滚 setTransactionTimeout:设置事务的事件,超过这个事件,就抛出异常,回滚事务 这里,值得注意的是,不是使用了UserTransaction就能把普通的JDBC操作直接转成JTA操作,JTA对DataSource、Connection和Resource 都是有要求的,只有符合XA规范,并且实现了XA规范的相关接口的类才能参与到JTA事务中来,关于XA规范,请看我的另外一篇文章中有相关介绍。这里,提一句,目前主流的数据库都支持XA规范。 要想使用用 JTA 事务,那么就需要有一个实现 javax.sql.XADataSource 、 javax.sql.XAConnection 和 javax.sql.XAResource 接口的 JDBC 驱动程序。一个实现了这些接口的驱动程序将可以参与 JTA 事务。一个 XADataSource 对象就是一个 XAConnection 对象的工厂。XAConnection 是参与 JTA 事务的 JDBC 连接。 要使用JTA事务,必须使用XADataSource来产生数据库连接,产生的连接为一个XA连接。 XA连接(javax.sql.XAConnection)和非XA(java.sql.Connection)连接的区别在于:XA可以参与JTA的事务,而且不支持自动提交。 public void JtaTransfer() { javax.transaction.UserTransaction tx = null; java.sql.Connection conn = null; try{ tx = (javax.transaction.UserTransaction) context.lookup("java:comp/UserTransaction"); //取得JTA事务,本例中是由Jboss容器管理 javax.sql.DataSource ds = (javax.sql.DataSource) context.lookup("java:/XAOracleDS"); //取得数据库连接池,必须有支持XA的数据库、驱动程序 tx.begin(); conn = ds.getConnection(); // 将自动提交设置为 false, //若设置为 true 则数据库将会把每一次数据更新认定为一个事务并自动提交 conn.setAutoCommit(false); stmt = conn.createStatement(); // 将 A 账户中的金额减少 500 stmt.execute("\ update t_account set amount = amount - 500 where account_id = 'A'"); // 将 B 账户中的金额增加 500 stmt.execute("\ update t_account set amount = amount + 500 where account_id = 'B'"); // 提交事务 tx.commit(); // 事务提交:转账的两步操作同时成功 } catch(SQLException sqle){ try{ // 发生异常,回滚在本事务中的操做 tx.rollback(); // 事务回滚:转账的两步操作完全撤销 stmt.close(); conn.close(); }catch(Exception ignore){ } sqle.printStackTrace(); } } 上面的例子就是一个使用JTA事务的转账操作,该操作相对依赖于J2EE容器,并且需要通过JNDI的方式获取UserTransaction和Connection。 标准的分布式事务 一个分布式事务(Distributed Transaction)包括一个事务管理器(transaction manager)和一个或多个资源管理器(resource manager)。一个资源管理器(resource manager)是任意类型的持久化数据存储。事务管理器(transaction manager)承担着所有事务参与单元者的相互通讯的责任。 JTA的实现方式也是基于以上这些分布式事务参与者实现的,具体的关于JTA的实现细节不是本文的重点,感兴趣的同学可以阅读JTA 深度历险 – 原理与实现 看上面关于分布式事务的介绍是不是和2PC中的事务管理比较像?的却,2PC其实就是符合XA规范的事务管理器协调多个资源管理器的一种实现方式。 我之前有几篇文章关于2PC和3PC的,那几篇文章中介绍过分布式事务中的事务管理器是如何协调多个事务的统一提交或回滚的,后面我还会有几篇文章详细的介绍一下和分布式事务相关的内容,包括但不限于全局事务、DTP模型、柔性事务等。 JTA的优缺点 JTA的优点很明显,就是提供了分布式事务的解决方案,严格的ACID。但是,标准的JTA方式的事务管理在日常开发中并不常用,因为他有很多缺点: 实现复杂 通常情况下,JTA UserTransaction需要从JNDI获取。这意味着,如果我们使用JTA,就需要同时使用JTA和JNDI。 JTA本身就是个笨重的API 通常JTA只能在应用服务器环境下使用,因此使用JTA会限制代码的复用性。 总结 Java事务的类型有三种:JDBC事务、JTA(Java Transaction API)事务、容器事务,其中JDBC的事务操作用法比较简单,适合于处理同一个数据源的操作。JTA事务相对复杂,可以用于处理跨多个数据库的事务,是分布式事务的一种解决方案。 这里还要简单说一下,虽然JTA事务是Java提供的可用于分布式事务的一套API,但是不同的J2EE平台的实现都不一样,并且都不是很方便使用,所以,一般在项目中不太使用这种较为负责的API。现在业内比较常用的分布式事务解决方案主要有异步消息确保型、TCC、最大努力通知等。关于这几种分布式事务解决方案,我会在后面的文章中介绍。欢迎关注与交流。 参考资料 JTA 深度历险 – 原理与实现 事务模型与分布式事务总结思考
技术
# 分布式
酷游
1月22日
0
6
0
2025-01-22
关于分布式一致性的探究
随着大型网站的各种高并发访问、海量数据处理等场景越来越多,如何实现网站的高可用、易伸缩、可扩展、安全等目标就显得越来越重要。为了解决这样一系列问题,大型网站的架构也在不断发展。提高大型网站的高可用架构,不得不提的就是分布式。在初识分布式系统一文中简单介绍了分布式的基本概念,本文将在上篇文章的基础上继续学习分布式的一致性问题。主要介绍分布式一致性的基本概念、重要性、一致性模型等。 一致性的重要性 分布式领域CAP理论告诉我们,任何一个分布式系统都无法同时满足Consistency(一致性),Availability(可用性), Partition tolerance(分区容错性) 这三个基本需求。最多只能满足其中两项。 但是,一个分布式系统无论在CAP三者之间如何权衡,都无法彻底放弃一致性(Consistency),如果真的放弃一致性,那么就说明这个系统中的数据根本不可信,数据也就没有意义,那么这个系统也就没有任何价值可言。所以,无论如何,分布式系统的一致性问题都需要重点关注。(分布式系统的CAP理论、分布式系统的BASE理论) 这里先简单提一下,由于一个分布式系统不可能放弃一致性,那么为什么有的架构师还说在某些场景中可以牺牲一致性呢?通常这里说的放弃一致性指的是放弃数据的强一致性(后文介绍什么是强一致性)。 通常情况下,我们所说的分布式一致性问题通常指的是数据一致性问题。那么我们就先来了解一下什么是数据一致性。 数据一致性 数据一致性其实是数据库系统中的概念。我们可以简单的把一致性理解为正确性或者完整性,那么数据一致性通常指关联数据之间的逻辑关系是否正确和完整。我们知道,在数据库系统中通常用事务(访问并可能更新数据库中各种数据项的一个程序执行单元)来保证数据的一致性和完整性。而在分布式系统中,数据一致性往往指的是由于数据的复制,不同数据节点中的数据内容是否完整并且相同。 比如在集中式系统中,有一些关键的配置信息,可以直接保存在服务器的内存中,但是在分布式系统中,如何保存这些配置信息,又如何保证所有机器上的配置信息都保持一致,又如何保证修改一个配置能够把这次修改同步到所有机器中呢? 再比如,在集中式系统中,进行一个同步操作要写同一个数据的时候,可以直接使用事务+锁来管理保证数据的ACID。但是,在分布式系统中如何保证多台机器不会同时写同一条数据呢? 除了上面提到的同一个数据的一致性,还有一种情况也可以叫做数据的一致性:比如我们在电商网站下单,需要经历扣减库存、扣减红包、扣减折扣券等一系列操作。如果库存库存扣减成功,但是红包和折扣券扣减失败的话,也可以说是数据没有保证一致性。 如何保证数据的一致性,是分布式系统中必须面对的问题。 为什么会有数据一致性问题 在初识分布式系统中我们介绍过,虽然分布式系统有着诸多优点,但是由于采用多机器进行分布式部署的方式提供服务,必然存在着数据的复制(如数据库的异地容灾,多地部署)。分布式系统的数据复制需求主要来源于以下两个原因: 可用性。将数据复制到分布式部署的多台机器中,可以消除单点故障。防止系统由于某台(些)机器宕机导致的不可用。 性能。通过负载均衡技术,能够让分布在不同地方的数据副本全都对外提供服务。有效提高系统性能。 分布式系统为了提升可用性和性能,会通过复制技术来进行数据同步。复制机制的目的是为了保证数据的一致性。但是数据复制面临的主要难题也是如何保证多个副本之间的数据一致性。在分布式系统引入复制机制后,不同的数据节点之间由于网络延时等原因很容易产生数据不一致的情况。 如果上面提到的数据复制场景你不是很熟悉的话,下面这个例子你肯定遇到过。就是现在很多网站都是微服务化的,一个网站被垂直拆分成多个功能模块。各模块之间独立部署。模块间通过RPC或者HTTP交互。由于这种RPC或者HTTP的交互可能存在网络延迟导致超时的情况。甚至被调用方也有可能执行出错等情况,这时候就可能导致数据不一致。 比如下单操作要依次扣减红包、扣减折扣券、扣减库存。在下单应用的执行过程中,调用红包系统扣减红包成功了,但是再调用折扣券系统扣减折扣券的时候网络超时了。这时候下单应用根本不知道折扣券系统到底有没有执行成功。这时候他就需要一些机制来决定是要回滚红包的扣减,还是继续执行库存的扣减。这种机制,其实就是数据一致性的解决方案了。 由于应用分布式部署,就无法通过数据库事务保证多个写操作的原子性。一旦某个操作失败,其他操作如果不回滚的话就会发生数据不一致问题。 因此,如何能既保证数据一致性,又保证系统的性能,是每一个分布式系统都需要重点考虑和权衡的。一致性模型可以在做这些权衡的时候给我们很多借鉴和思考。 一致性模型 强一致性 当更新操作完成之后,任何多个后续进程或者线程的访问都会返回最新的更新过的值。这种是对用户最友好的,就是用户上一次写什么,下一次就保证能读到什么。 但是这种实现对性能影响较大,因为这意味着,只要上次的操作没有处理完,就不能让用户读取数据。 弱一致性 系统并不保证进程或者线程的访问都会返回最新的更新过的值。系统在数据写入成功之后,不承诺立即可以读到最新写入的值,也不会具体的承诺多久之后可以读到。但会尽可能保证在某个时间级别(比如秒级别)之后,可以让数据达到一致性状态。 最终一致性 弱一致性的特定形式。系统保证在没有后续更新的前提下,系统最终返回上一次更新操作的值。在没有故障发生的前提下,不一致窗口的时间主要受通信延迟,系统负载和复制副本的个数影响。DNS是一个典型的最终一致性系统。 最终一致性模型的变种 因果一致性:如果A进程在更新之后向B进程通知更新的完成,那么B的访问操作将会返回更新的值。如果没有因果关系的C进程将会遵循最终一致性的规则。 读己所写一致性:因果一致性的特定形式。一个进程总可以读到自己更新的数据。 会话一致性:读己所写一致性的特定形式。进程在访问存储系统同一个会话内,系统保证该进程读己之所写。 单调读一致性:如果一个进程已经读取到一个特定值,那么该进程不会读取到该值以前的任何值。 单调写一致性:系统保证对同一个进程的写操作串行化。 上述最终一致性的不同方式可以进行组合,例如单调读一致性和读己之所写一致性就可以组合实现。并且从实践的角度来看,这两者的组合,读取自己更新的数据,和一旦读取到最新的版本不会再读取旧版本,对于此架构上的程序开发来说,会少很多额外的烦恼。 为了解决分布式的一致性问题,在长期的研究探索过程中,涌现出了一大批经典的一致性协议和算法,其中比较著名的有二阶段提交协议,三阶段提交协议和Paxos算法。 下一篇文章将介绍这些和分布式一致性相关的协议和算法。
技术
# 分布式
酷游
1月22日
0
4
0
2025-01-22
分布式系统的BASE理论
BASE理论 eBay的架构师Dan Pritchett源于对大规模分布式系统的实践总结,在ACM上发表文章提出BASE理论,BASE理论是对CAP理论的延伸,核心思想是即使无法做到强一致性(Strong Consistency,CAP的一致性就是强一致性),但应用可以采用适合的方式达到最终一致性(Eventual Consitency)。 BASE是指基本可用(Basically Available)、软状态( Soft State)、最终一致性( Eventual Consistency)。 基本可用(Basically Available) 基本可用是指分布式系统在出现故障的时候,允许损失部分可用性,即保证核心可用。 电商大促时,为了应对访问量激增,部分用户可能会被引导到降级页面,服务层也可能只提供降级服务。这就是损失部分可用性的体现。 软状态( Soft State) 软状态是指允许系统存在中间状态,而该中间状态不会影响系统整体可用性。分布式存储中一般一份数据至少会有三个副本,允许不同节点间副本同步的延时就是软状态的体现。mysql replication的异步复制也是一种体现。 最终一致性( Eventual Consistency) 最终一致性是指系统中的所有数据副本经过一定时间后,最终能够达到一致的状态。弱一致性和强一致性相反,最终一致性是弱一致性的一种特殊情况。 ACID和BASE的区别与联系 ACID是传统数据库常用的设计理念,追求强一致性模型。BASE支持的是大型分布式系统,提出通过牺牲强一致性获得高可用性。 ACID和BASE代表了两种截然相反的设计哲学 在分布式系统设计的场景中,系统组件对一致性要求是不同的,因此ACID和BASE又会结合使用。 参考资料 CAP和BASE理论
技术
# 分布式
酷游
1月22日
0
8
0
2025-01-22
分布式一致性算法——paxos
随着大型网站的各种高并发访问、海量数据处理等场景越来越多,如何实现网站的高可用、易伸缩、可扩展、安全等目标就显得越来越重要。为了解决这样一系列问题,大型网站的架构也在不断发展。提高大型网站的高可用架构,不得不提的就是分布式。在关于分布式事务、两阶段提交协议、三阶提交协议一文中主要用于解决分布式一致性问题的集中协议,那么这篇文章主要讲解业内公认的比较难的也是最行之有效的paxos算法。 我认为对paxos算法讲解的最清楚的就是维基百科了。但是要看懂维基百科中的介绍需要很强的数学思维(paxos毕竟是一个算法),而且有很多关于定理的推论、证明等过程。那么本篇文章主要站在程序的角度,通俗的,循序渐进的讲解到底什么是paxos算法。 背景 Google Chubby的作者Mike Burrows说过, there is only one consensus protocol, and that’s Paxos” – all other approaches are just broken versions of Paxos. 意即世上只有一种一致性算法,那就是Paxos,所有其他一致性算法都是Paxos算法的不完整版。 Paxos算法是莱斯利·兰伯特(Leslie Lamport,就是 LaTeX 中的”La”,此人现在在微软研究院)于1990年提出的一种基于消息传递的一致性算法。为描述 Paxos 算法,Lamport 讲述了这样一个故事: 在古希腊有一个岛屿叫做Paxos,这个岛屿通过议会的形式修订法律。执法者(legislators,后面称为牧师priest)在议会大厅(chamber)中表决通过法律,并通过服务员传递纸条的方式交流信息,每个执法者会将通过的法律记录在自己的账目(ledger)上。问题在于执法者和服务员都不可靠,他们随时会因为各种事情离开议会大厅、服务员也有可能重复传递消息(或者直接彻底离开),并随时可能有新的执法者(或者是刚暂时离开的)回到议会大厅进行法律表决,因此,议会协议要求保证上述情况下可以能够正确的修订法律并且不会产生冲突。 什么是paxos算法 Paxos 算法是分布式一致性算法用来解决一个分布式系统如何就某个值(决议)达成一致的问题。 人们在理解paxos算法是会遇到一些困境,那么接下来,我们带着以下几个问题来学习paxos算法: 1、paxos到底在解决什么问题? 2、paxos到底如何在分布式存储系统中应用? 3、paxos的核心思想是什么? paxos解决了什么问题 在关于分布式一致性的探究中我们提到过,分布式的一致性问题其实主要是指分布式系统中的数据一致性问题。所以,为了保证分布式系统的一致性,就要保证分布式系统中的数据是一致的。 在一个分布式数据库系统中,如果各节点的初始状态一致,每个节点都执行相同的操作序列,那么他们最后能得到一个一致的状态。为保证每个节点执行相同的命令序列,需要在每一条指令上执行一个“一致性算法”以保证每个节点看到的指令一致。 所以,paxos算法主要解决的问题就是如何保证分布式系统中各个节点都能执行一个相同的操作序列。 上图中,C1是一个客户端,N1、N2、N3是分布式部署的三个服务器,初始状态下N1、N2、N3三个服务器中某个数据的状态都是S0。当客户端要向服务器请求处理操作序列:op1op2op3时(op表示operation)(这里把客户端的写操作简化成向所有服务器发送相同的请操作序列,实际上可能通过Master/Slave模式处理)。如果想保证在处理完客户端的请求之后,N1、N2、N3三个服务器中的数据状态都能从S0变成S1并且一致的话(或者没有执行成功,还是S0状态),就要保证N1、N2、N3在接收并处理操作序列op1op2op3时,严格按照规定的顺序正确执行opi,要么全部执行成功,要不就全部都不执行。 所以,针对上面的场景,paxos解决的问题就是如何依次确定不可变操作opi的取值,也就是确定第i个操作什么,在确定了opi的内容之后,就可以让各个副本执行opi操作。 Paxos算法详解 Paxos是一个十分巧妙的一致性算法,但是他也十分难以理解,就连他的作者Lamport都被迫对他做过多种讲解。我认为对paxos算法讲解的最清楚的就是维基百科了。但是要看懂维基百科中的介绍需要很强的数学思维(paxos毕竟是一个算法),而且有很多关于定理的推论、证明等过程。那么本篇文章主要站在程序的角度,通俗的,循序渐进的讲解到底什么是paxos算法。 我们先把前面的场景简化,把我们现在要解决的问题简化为如何确定一个不可变变量的取值(每一个不可变变量可以标识一个操作序列中的某个操作,当确保每个操作都正确之后,就可以按照顺序执行这些操作来保证数据能够准确无误的从一个状态转变成另外一个状态了)。 接下来,请跟我一步一步的学习paxos算法。 要学习paxos算法,我们就要从他要解决的问题出发,假如没有paxos算法,当我们面对如何确定一个不可变变量的取值这样一个吻问题的时候,我们应该如何解决呢? 这里暂不介绍paxos中的角色的概念,读者可以自行从维基百科中了解。不了解的话也可以直接往下看,看着看着就了解了。 问题抽象 我们把确定一个不可变变量的取值问题定义成: 设计一个系统,来存储名称为var的变量。 var的取值可以是任意二进制数 系统内部由多个Accepter组成,负责管理和存储var变量。 系统对外提供api,用来设置var变量的值propose(var,V) => or 将var的值设置为V,系统会返回ok和系统中已经确定的取值f,或者返回error。 外部有多个Proposer机器任意请求系统,调用系统API(propose(var,V) => or )来设置var变量的值。 如果系统成功的将var设置成了V,那么返回的f应该就是V的值。否则,系统返回的f就是其他的Proposer设置的值。 > 系统需要保证var的取值满足一致性 如果var没有被设置过,那么他的初始值为null 一旦var的值被设置成功,则不可被更改,并且可以一直都能获取到这个值 系统需要满足容错特性 可以容忍任意proposer出现故障可以容忍少数acceptor故障(半数以下) 暂时忽略网络分化问题和acceptor故障导致var丢失的问题。 到这里,问题已经抽象完成了,读者可以再仔细看看上面的系统描述。如果这样设置一个系统,是不是就可以保证变量var的不可变性了呢? 这里还是再简单讲解一下,上面的系统确实可以保证变量var的不可变性。 因为var的初始值为null,当有proposer请求接口propose(var,v)设置var的值的时候,系统会将var设置为v,并返回f(f==v)。 var变量被初始化以后,再有proposer请求propose(var,v)设置var的值的时候,系统会直接返回系统中已有的var的值f,而放弃proposer提供的v。 系统难点 要设计以上系统存在以下难点: 1、管理多个proposer并发执行 2、容忍var变量的不可变性 3、容忍任意Proposer的故障 4、容忍半数以下的acceptor的故障 解决方案一 先考虑整个系统由单个acceptor组成。通过类似互斥锁的方式来管理并发的proposer的请求。 proposer向acceptor申请acceptor的互斥访问权,当取得互斥访问权之后才能调用api给var变量赋值。accepter向proposer发放互斥访问权,谁取得了互斥访问权,acceptor就接收谁的请求。这样通过互斥访问的机制,proposer就要按照获取互斥访问权的顺序来请求系统。一旦acceptor接收到一个proposer请求,并成功给var变量赋值之后,就不再允许其他的proposer设置var变量的值。每当再有proposer来请求设置var变量的值的时候,acceptor就会将var里面现有的值返回给他。 基于互斥访问权的acceptor的实现 acceptor会保存变量var的值和一个互斥锁Lock。 提供接口prepare() 加互斥锁,给予var的互斥访问权,并返回当前var的取值 提供接口release() 用于释放互斥访问权 提供接口accept(var, v) 如果已经加锁,并且当前var没有值,则将var的值设置成v,并释放锁。 proposer采用两阶段来实现 Step1、通过调用prepare接口来获取互斥性访问权和当前var的取值 如果无法获取到互斥性访问权,则返回 ,并不能进入到下一个阶段,因为其他proposer获取到了互斥性访问权。 Step2、根据当前var的取值f选择执行 1、如果f的取值为null,说明没有被设置过值,则调用接口accept(var ,v)来将var的取值设置成v,并释放掉互斥性访问权。2、如果f的取值不为null,说明var已经被其他proposer设置过值,则调用release接口释放掉互斥性访问权。 总结:方案一通过互斥访问的方式来保证所有的proposer能够串行的访问acceptor,这样其实并没有解决多个proposer并发执行的问题。只是想办法绕开了并发执行。虽然可以在一定程度上保证var变量的取值是确定的。但是一旦获取到互斥访问权的proposer在执行过程中出现故障,那么就会导致所有其他proposer无法再获取到互斥访问权,就会发生死锁。。所以,方案一不仅效率低、而且还会产生死锁问题,不能容忍任意Proposer出现故障。在之前提到的四个系统难点中,方案一可以解决难点1和难点2,但是无法解决难点3和难点4。 解决方案二 通过引入抢占式访问权来取代互斥访问权。acceptor有权让任意proposer的访问权失效,然后将访问权发放给其他的proposer。 在方案二中,proposer向acceptor发出的每次请求都要带一个编号(epoch),且编号间要存在全序关系。一旦acceptor接收到proposer的请求中包含一个更大的epoch的时候,马上让旧的epoch失效,不再接受他们提交的取值。然后给新的epoch发放访问权,让他可以设置var变量的值。 为了保证var变量取值的不变性,不同epoch的proposer之前遵守后者认同前者的原则: 在确保旧的epoch已经失效后,并且旧的epoch没有设置var变量的值,新的epoch会提交自己的值。当旧的epoch已经设置过var变量的取值,那么新的epoch应该认同旧的epoch设置过的值,并不在提交新的值。 基于抢占式访问权的acceptor的实现 下面是一个讲解paxos算法的视频~! [tudou id=e8zM8dAL6hM ]
技术
# 分布式
酷游
1月22日
0
5
0
2025-01-22
Zookeeper介绍(一)——背景知识
本文主要介绍什么是分布式系统以及分布式系统存在哪些问题。 分布式 互联网技术的发展,导致大型网站需要的计算能力和存储能力越来越高。网站架构逐渐从集中式转变成分布式。 什么是分布式 把一个计算任务分解为若干个计算单元,并分派到若干个不同的计算机中去执行,然后再汇总计算结果。 分布式的工作方式有点类似于团队合作。当有一项任务分配到某个团队之后,团队内部的成员开始各司其职,然后把工作结果统一汇总给团队主管,由团队主管再整理团队的工作成果汇报给公司。 分布式存在的问题 虽然分布式和集中式系统相比有很多优势,比如能提供更强的计算、存储能力,避免单点故障等问题。但是由于采用分布式部署的方式,就经常会出现网络故障等问题,并且如何在分布式系统中保证数据的一致性和可用性也是一个比较关键的问题。 比如在集中式系统中,有一些关键的配置信息,可以直接保存在服务器的内存中,但是在分布式系统中,如何保存这些配置信息,又如何保证所有机器上的配置信息都保持一致,又如何保证修改一个配置能够把这次修改同步到所有机器中呢? 再比如,在集中式系统中,进行一个同步操作要写同一个数据的时候,可以直接使用事务+锁来管理保证数据的ACID。但是,在分布式系统中如何保证多台机器不会同时写同一条数据呢? 还有很多诸如此类的问题,大部分都是围绕着分布式系统中的数据的一致性问题。
技术
# 分布式
酷游
1月22日
0
19
0
上一页
1
2
3
4
下一页
易航博客