1、分布式分布式旅行预定旅行预定系统系统项目表述:项目目标是用 java 或 VC 组建一个分布式应用系统,它用来实施一个简单的旅行预定系统。要求有两个阶段来实施系统:PART 1:做一个简单的资源管理器(RM)(例如:一个简单的数据库系统包括一组固定的表和操作集合)支持具有 ACID 属性的并发事务。PART 2:实现一个工作流管理器(WC)和一个事务管理器(TM),能在各个资源管理者(RM)之间实现分布式事务处理。PART 3:实现这些基础项目的外部增设功能。PART 1:简单旅行预定资源管理器实现一个简单的资源管理器(RM),支持具有 ACID 属性的并发交互事务。特别的,资源管理器储存关于:飞机票,租车,旅馆房间和旅客的数据。多客户机通过接口界面并发访问资源管理器来查询和更新数据。要求资源管理器保证这些并发事务执行的正确性,例如,在有 ACID 要求的事务中。概念上,资源管理器要储存下列的表:FLIGHTS (String flightNum, int price, int numSeats, int numAvail) HOTELS (String location, int p
2、rice, int numRooms, int numAvail) CARS (String location, int price, int numCars, int numAvail) CUSTOMERS (String custName) RESERVATIONS(String custName, int resvType, String resvKey) 为了更简单,我们给出了下列假设:1. 只有一个航班,并且在给定的航班上所有的座位都是相同的价钱;flightnum 是 FLIGHTS 的主键。2. 所有的旅馆房间在同一个地方的都是相同的价钱:location是 HOTELS 的主键。3. custNum 是 CUSTOMERS 的主键。4. RESERVATIONS 表包括一个对应的项目表,这张表由用户对航班,汽车,旅馆的预定信息组成,如下:(1 代表航班,2代表旅馆房间,3 代表汽车),并且 resvKey 是这张保留项目表的主键。5. 在 FLIGHTS 表中,numAvail 是一个给定航班可以预定到的座位号。对一个给定的 flightNum,数据库的一个一致性情况是
3、:预订表中一个航班的总的预定数加上空闲的座位数,必须等于航班上的座位总数。对于汽车和旅馆房间表也是一样的情况。我们要提供资源管理器的应用程序界面(Resource Manager API).在其他的事情中,界面要允许每个资源管理器储存的表进行属性的添加,删除,和更改操作。我们的工作是要写我们提供的界面的应用程序。资源管理器支持交互事务。一个事务通过调用资源管理器的start()程序来从中获取一个唯一的事务 id。所有对 RM 的子调用都将包含这个事务 id。最后,事务调用 commit()或者abort()。一个典型的用户事务可能如下:当然在现实中我们会检验返回值并且发现一些例外,同样可以将 Client.java 看作一个简单的例子。Int xid=rm.start();/如果足够便宜并且有剩余的座位If(rm.queryFlightPrice(xid,”347”)0)Rm.reserveFlight(xid,”John”,”347”);Rmit(xid);并发控制是基于两阶段锁协议的。特别的,当一个用户请求查询或更新信息时,资源管理器要保证适当的加锁,并且当一事务提交或者撤销后要释
4、放掉所有的锁。我们提供了LockManager 来帮助完成这项任务。这个 LockManager 支持下面的应用程序界面:Lock(xid,thingBeingLocked,read/write) throwsDeadlockExceptionunLockAll(xid)就如前面所说,Xid 是一个事务唯一的标识。这个锁管理器通过一个超时机制(当前设定为 10 秒)来解决死锁。一个失败的锁(死锁)的处理是抛出一个 DeadLockException(死锁例外)。这个死锁管理器同样要解决锁变换,也就是所说的锁更新的情况。锁更新,常发生在一个事务对一个资源加了读锁之后,要对其进行写操作要加上写锁的情况。Lock(xid,foo,read);/读 fooLock(xid,foo,write);/写 foo其他的事务可能以及在对 foo 进行读操作,所以死锁很可能在所更新时发生。开始了:我们的程序最好在自己的机器上完成,我们自己安装一个 java环境。当我们提交程序是,要测试并且确保我们的程序完成并顺利运行,我们要对程序进行测试。应用程序界面提供的程序库,要包含两个包:lockmgr 和tra
5、nsaction.lockmgr 包要提供基本的 lockMananger 类.我们不需要更改这个包里的值。在事务包中有基本的类,用来启动应用程序。它包括资源管理器的界面。提醒一下,我们也不必去更改这个文件。我们的资源管理器的应用程序文件要放在名叫 ResourceManagerImpl 的一个类中。这个类中还可以放我们必要时定义的新类。这个现有的 ResourceManagerImpl.java 中还有一些没有用的应用程序我们要先删除。事务的说明中还有一个用户的简单的 Client.java。在我们的系统中,我们要写更多的更成熟的用户来测试我们的资源管理器,但是我们并不要求把他们包含到系统中。事实上,我们可以用程序和 Client.java 版本连接起来,来测试一下我们的系统是否对所有的情况都能正确地处理。用户通过 Java RMI(远程方法调用)来和 RM 交互。我们可以找到一种在 RMI 上的监护指示程序。尽管,用户和我们的 toy ResourceManagerImpl 已经有了所有的 RMI 程序。我们要做的唯一的事就是更改事务的第一行,去给自己一个唯一的 RMI 注册号码,
6、这样我们就不会和其他的 347 的用户冲突。我们要提交份源文件和一个简短的只读文件。完成建议:这有一些建议来完成要求的系统:1. 基础的资源管理器:开始时忽略细节。忽略掉一些障碍并且假设这些数据都存储在存储器中。一个要完成的工作是要把数据都存储在一张或多张 hash 表中。我们要在每个数据库中加一张 hash 表,或者将数据库中的表合并成一张 hash 表。表的每一行有一个 hash 入口,由表的主键来标记。我们可以使用一个 java 类来标记各种不同的行。例如:一个基于FLIGHTS 的类,有数据来标识,flightNum,price,numstates,和numAvail预订表中没有主键,但是可以通过 custNum 来找到用户,所以一个可能的方案是将其和 CUSTOMERS 表合并。也就是说要有一个 hash 表建立 custNum 的索引,同时要有一个 hash 表包含一对(resvType,resvKey)。考虑到在同一个地方的租用汽车价钱相同,所以下面的addCars(T1, “San Diego“, 4, $52);addCars(T2, “San Diego“, 7,
7、$54);应该是有 11 辆车 54 美元一起添加,而不是 4 辆 52 美元,7 辆 54 美元。2. 原子性。保持两个内存数据库副本,并且有一个指向动态副本。保持一个活动的事务更新在一个独立的 hash 表上。当一个事务提交后,合并事务的更新到一个没有活动过的数据库副本上,并且去除活动数据库的标示。在现有的系统中,唯一的不足是去操作一个撤销。当进程终止而内存数据消失时,并不需要对数据库进行 recover()。3. 隔离性。资源管理器要对每个事务适当的锁定数据,并且在事务提交或撤销后,释放所有的锁。我们可以在这里通过对不同阶段的加锁来测试程序。并且我们应尽可能的在一个阶段加上操作所用到的锁。RM 还要适当处理死锁:当一个事务死锁时,RM 要强行撤销事务。4. 持续性。对 RM 进行了更改,当事务提交后。所有数据都要一直放到磁盘上。测试:我们将使用多用户和单资源管理器来测试 RM 性能。RM 的技术界面被定义的易于测试出错误。Shutdown()程序要能用来合理优雅的关闭程序。在这种情况下,是说,等待所有的事务终止,并且清空文件。这样下次启动时,并不会试图重做事务。Diedown()
8、使得 RM 能迅速调用 System.exit(),来模拟系统失败。在当前状态离开数据库。当 RM 下次启动时,它将回到一个一致性状态。而不是马上 killing RM dieBeforePointerSwitch()和 dieAfterPointerSwitch()被调用会给 RM一个标记来调用 System.exit()在提交操作执行时。更多的细节要参照应用程序界面。PART 2:分布式事务管理器在项目的第二部分中,我们将把数据表分布在几个 RM 中,并在各个 RM 之间进行分布式事务操作。STEP1.完成一个工作流控制器。这个工作流控制器将是个前端的,这样就可使 RM 上的永久数据不会暴露在用户面前。为了达到这样的效果,工作流控制器要支持和 RM 相同的界面和下面的新功能:reserveItinerary(int xid, String custName, List flightNumList, String location, boolean needCar, boolean needRoom) 这个 reserveItinerary 表是工作流控制器相关的一种高层操作。参数有
9、:xid(事务 id)custNum(用户名),flightNumList(一张说有航班的号码表),location(旅行房间和汽车可能会被预订的地方),needCar/needRoom(真表示用户需要一辆车/房间)。在这里将 PART1 中的 RM 程序集成到 ResourceManager.java 中。在这里可以重利用 PART1 中的很多程序。工作流控制器的修改去面向一个特殊的 RM 的调用。例如用户将请求工作流管理器,预定一个航班 435 和 534 并且要租用一辆汽车在 St.Louis,这时工作流管理器启动一个事务,和 RM1 交互去预订一个航班 435,和 RM1 交互预订一个航班534,和 RM2 交互在 St.Louis 预订汽车。正如前面所提到的,现在要用到两个 RM,所以还有很多细节要工作流管理器来控制。STEP2.完成一个事务管理器(TM)。TM 支持下列操作:start,commit,abort,enlist.事务管理器是在各个不同的 RM 之间进行分布式事务的合作。TM 的界面有如下的作用:当对一个 RM 提出请求时,将调用 TM 的 enlist 程序来告诉 TM有一个事务。TM 将对事务要使用到的 RM 做标记。工作流控制器将用户的 start/commit/abort 调用直接提交给 TM 来处理。用户所有其他的调用也将被交到适当的 RM。因为 TM 和 RM 存在于工作流控制器的界面后,所以他们并没有用户可以直接使用的界面。在启动时,RM 将获得一个 TM(要通过 RMI 命名)的权限。工作流控制器同时启动了 RM 和 TM。TM 得到要使用到的 RM 表。同时,RM 也获得了一个 TM 权限的表。STEP3.运行多个 RM。将flights,cars,rooms,customers/reservations 数据分别放入一个 RM。TM 有一张表来标示那个事务将用到那个 RM。工作流控制器将决定那些请求/事务去那个 RM。当一个请求提交/撤销时,TM 调用适当的机制来对事务用到的所有 RM 进行相应操作。STEP4.完成一个两阶段提交协议(2PC)。在这个阶段,程序要完成一个可以进行故障恢复的 2PC。STEP5.现在考虑一下事务失败时的情况。特别的,在事务提交过程中的失败
《分布式旅行预定系统》由会员ji****72分享,可在线阅读,更多相关《分布式旅行预定系统》请在金锄头文库上搜索。