使用 WebSphere 中间件构建高可用性数据库环境,第 3 部分: 在 WebSphere Application Server 中使用 Oracle RAC 处理两阶段提交

在支持两阶段提交分布式事务的 IBM® WebSphere® Application Server 环境中使用 Oracle® 10g Real Application Cluster (RAC) 会导致一些微妙的事务恢复问题。本文介绍了在 WebSphere Application Server 集群环境中配置 RAC 的简单策略,该策略可提供故障转移和负载平衡,从而避免了事务恢复问题。 本文来自于 IBM WebSphere Developer Technical Journal

Soloman Barghouthi (soloman@us.ibm.com), WebSphere 架构师, IBM

Soloman Barghouthi 是 IBM Rochester Lab 的软件工程师。Soloman 是作为 San Francisco 项目的开发人员开始他在 IBM 的工作生涯的,目前他是 WebSphere Application Server Relational Resource Adapter (RRA) 架构师,并且是 Scheduler、AsynchBean 和 ObjectPool 组件的团队负责人。Soloman 是一位数据库专家和 WebSphere Application Server/Oracle 驻外人员。Soloman 负责研究传统数据库如何与 WebSphere Application Server 进行交互。


developerWorks 投稿作者

Dr. Debasish Banerjee (debasish@us.ibm.com), WebSphere 顾问, IBM

Debasish Banerjee 目前是 IBM Software Services 中的 WebSphere 顾问。他是作为 WebSphere 国际化架构师开始他的 WebSphere 生涯的。他特别感兴趣的领域是 WebSphere 和 WebSphere Process Server 环境的工作负载管理、高可用性和灾难恢复。Debasish 在基于组合程序的函数编程语言领域获得了博士学位。



2008 年 1 月 28 日

引言

对于访问 Oracle 数据库而言,Oracle Real Application Cluster (RAC) 可用于高可用性和工作负载管理。可以将 Oracle JDBC 驱动程序配置为在 IBM WebSphere Application Server 环境中提供这两种服务质量。遗憾的是,使用 10g 版本的 Oracle JDBC 驱动程序在多个 Oracle RAC 节点中进行工作负载管理会造成微妙的两阶段提交 (2PC) 分布式事务恢复问题。

在简单介绍 Oracle RAC 之后,本文将说明此事务恢复问题背后的原因,并详细介绍用于 WebSphere Application Server 环境的简单 Oracle RAC 配置,该配置可以避免事务恢复问题。


关于 Oracle RAC

Oracle RAC 是一个可“共享一切”的体系结构,用于获得数据库高可用性和负载平衡,在此体系结构中,有两个或多个 Oracle RAC 节点集群在一起,共享同一存储区(图 1)。

RAC 节点通过高速互连连接在一起,此互连方式支持 Oracle 节点之间的快速通信,可以在启动、锁定信息、事务信息、数据等过程中交换各种类别的数据块所有权信息。

图 1. Oracle RAC 配置
图 1. Oracle RAC 配置

在 Oracle RAC 环境中,每个 Oracle 数据块都被赋予一个(且只有一个)“主”Oracle RAC 节点。该 Oracle RAC 节点的全局缓存服务 (GCS) 负责管理对这些数据块集的访问。当其中一个 Oracle 节点需要访问某个 Oracle 数据块时,它必须首先与该数据块协商。然后,该主节点的 GCS 或者指示请求的 Oracle 节点从磁盘中获取该数据块,或者指示该Oracle 数据块的当前持有者将被请求的数据块发送到请求节点。Oracle 尝试跨所有 RAC 节点统一分发该数据块的所有权。在 Oracle RAC 环境中,数据块大致相等的所有节点都将被指定为主节点。(如果 Oracle RAC 节点数是 Oracle 数据块数的约数,则所有 RAC 节点都是具有同样数量的数据块的主节点。)

使用 Oracle 数据库的 WebSphere Application Server 应用程序通过 Oracle JDBC 驱动程序获取数据库连接。在 Oracle RAC 环境中,可以将 Oracle JDBC 驱动程序配置为用于故障转移或负载平衡(或者同时用于两者)。如果将 JDBC 驱动程序配置为支持故障转移,则在 RAC 节点出现故障时,以前从故障节点中获取连接的 WebSphere Application Server 应用程序必须能够透明地切换到其他运行的 RAC 节点。(为了能够透明地切换,可以将应用程序编码为捕获 StaleConnection 异常,并重试指定的连接次数来获取新的连接句柄。在请求获取连接时,Oracle JDBC 驱动程序将从运行的 RAC 节点提供物理连接。)该 JDBC 驱动程序将从运行的 RAC 节点获取新的连接。事实上,当一个或多个 RAC 节点出现故障时,正确编码的 WebSphere Application Server 应用程序应能够继续以几乎无中断的方式正常运行,但前提是将 RAC 配置为用于高可用性,当然,还需要有一些 RAC 节点处于活动状态。(您可能会注意到应用程序在响应上出现瞬间延迟,这是因为,作为故障转移过程的一部分,Oracle 需要传输故障 RAC 节点所拥有的数据块并将其统一分发给其他运行的 RAC 节点。在此重构过程中,Oracle 将在短时间内冻结数据库。)

除高可用性外,还可以将 Oracle RAC 配置为提供工作负载平衡;数据库的工作负载平衡在连接级别发生。Oracle 使用随机算法把连接请求分发给 RAC 节点。对于每个连接请求,Oracle JDBC 驱动程序将随机选择一个 RAC 节点来获取连接。一般情况下,此类随机分发算法以统一方式使用全部 RAC 节点。例如,如果在两节点的 Oracle RAC 环境中进行 100 个数据库连接请求,则将使用每个 RAC 节点来获取大约 50 个数据库连接。

WebSphere Application Server 集群中的简单 RAC 配置

图 2 描述了 WebSphere Application Server 集群环境中的典型 RAC 物理拓扑,在此环境中,同时支持故障转移和负载平衡服务质量。

图 2. 使用 Oracle RAC 的 WebSphere Application Server 环境
图 2. 使用 Oracle RAC 的 WebSphere Application Server 环境

WebSphere Application Server 集群包括两个成员:cluster-member1 和 cluster-member2。Oracle RAC 物理配置包括两个节点:rac-node1 和 rac-node2。RAC 节点可以与 WebSphere 集群成员位于同一物理机制中,也可以位于完全不同的机制中,如图 2 所示。(实际位置并不影响 RAC 所提供的基本服务质量。)

为了实现高可用性和负载平衡,您可以为这两个 WebSphere 集群成员指定 Oracle 数据源 URL,如下所示:

清单 1
 jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=
        (ADDRESS=(PROTOCOL=TCP)(HOST= rac-node1)(PORT=1521))
        (ADDRESS=(PROTOCOL=TCP)(HOST= rac-node2)(PORT=1521))
        (FAILOVER=on)(LOAD_BALANCE=on)
  (CONNECT_DATA=(SERVER=DEDICATED)
        (SERVICE_NAME=<dbname>))) 				(1)

由于设置了 FAILOVER 属性,所以,如果任一 RAC 节点(例如 rac-node1)变得不可用,当请求新连接时,oracle JDBC 驱动程序将从另一仍在运行的 Oracle RAC 节点(在此情况下是 rac-node2)返回连接。

此外,由于将 LOAD-BALANCE 属性指定为“on”,所以 Oracle JDBC 驱动程序将同时从 rac-node1 和 rac-node2 为在 cluster-member1 和 cluster-member2 中运行的应用程序实例提供连接。如上所述,Oracle 将尝试从 rac-node1 和 rac-node2 中获取大致相同的物理连接数。

注意,如果关闭 LOAD_BALANCE 属性,则在数据源 URL 中指定 RAC 节点的顺序就变得非常重要。Oracle JDBC 驱动程序始终尝试从占据列表中第一位置的 RAC 节点获取物理连接。如果第一个 RAC 节点不可用,JDBC 驱动程序将尝试从第二个 RAC 节点中获取连接,依此类推。这说明,对于 URL (1)(在清单 1 中),cluster-member1 的 URL (rac-node1) 是 RAC 主节点。只要 rac-node1 仍在正常运行,将从 rac-node1 中为所有物理连接请求提供服务;rac-node2 不起任何作用。如果 rac-node1 出现故障,Oracle 将从 rac-node2 为 cluster-member1 中发出的连接请求提供服务,rac-node2 是 URL (1) 的第二个 RAC 节点。因此,只要 rac-node1 不能用,来自 cluster-member1 中的所有新连接请求都将由 rac-node2 提供服务。

在这种情况下,图 2 中的完整工作负载管理分两个级别提供。在 WebSphere Application Server 级别,工作负载管理由路由器组件(HTTP 服务器插件、ORB 插件、按需路由器等)提供,它将入站请求分发给适当的集群成员,并维护适当的关联(如果适用)。在入站请求到达在集群成员上执行的应用程序实例后,向数据库发出的新物理连接请求将由 Oracle JDBC 驱动程序在 rac-node1 和 rac-node2 之间进行负载平衡。

如果该应用程序不使用 2PC 分布式事务,上述简单配置就足够了。但是,如果在此简单和易于配置的设置中使用 2PC 分布式事务,可能会存在一些微妙的恢复问题,这将在下一部分中进行说明。


两阶段提交分布式事务和 RAC 配置

当恢复跨多个 Oracle RAC 节点的 2PC 分布式事务时,Oracle 10g RAC 存在一个固有的问题:在尝试提交或回滚以前在故障 RAC 节点中运行的事务分支(通过活动 RAC 节点)时,事务管理器可能会收到这样一条异常消息“ORA-24756:transaction does not exist”(ORA-24756:事务不存在)。之所以会发生此问题,是因为在 RAC 节点出现故障时,Oracle 将为业务打开其他仍然运行的 RAC 节点,即使在 Oracle RAC 完成与该故障 RAC 节点对应的必要恢复操作之前也如此。

下面是一个描述此问题的假定情形。假设有一个两节点的 Oracle 10G RAC 环境(带有节点 rac-node1 和 rac-node2),在此环境中,同时启用了故障转移和负载平衡:

  • 应用程序在 WebSphere Application Server 集群成员中启动了一个用户事务(称为 UTx)。
  • 在 UTx 边界内,该应用程序请求一个数据库连接。假定该连接是从 rac-node1 提供的。
  • 该应用程序向同一 Oracle 数据库资源管理器请求另一连接,该连接通过 rac-node2 提供,这是另一个 RAC 节点。
  • 这会在两个连接上同时执行工作,从而导致启动两个事务分支:TxB1 和 TxB2。
  • 假设在 WebSphere Application Server 事务管理器发出对 TxB1 的 xa.prepare() 调用之后并调用 xa.commit() 之前,RAC 节点 (rac-node1) 出现故障。
  • 这时,WebSphere 事务管理器将收到 XAER_RMFAIL 返回代码(请参阅参考资料),该代码指示资源管理器不可用。
  • WebSphere 事务管理器将尝试获取到 RAC 的新连接。由于支持故障转移,所以在 RAC 端完成恢复后(即已为业务打开 Oracle RAC),Oracle JDBC 驱动程序将从 rac-node2 提供连接。
  • WebSphere 事务管理器将通过发出 xa.commit() 尝试完成 TxB1。
  • Oracle JDBC 驱动程序可能会抛出 ORA-24756:事务不存在这一异常;仍然运行的 RAC 节点 rac-node2 甚至还不知道事务分支 TxB1。
  • TxB1 将处于一种未决状态,这时,如果 TxB1 正好持有某些数据库锁,则可能会导致问题。
  • 任何对被 TxB1 分支锁定的同一数据库行或表的后续访问尝试都将导致“ORA-01591 lock held by in-doubt distributed transaction”(ORA-01591 锁由未决的分布式事务持有)异常,从而导致数据库的某些部分不可用。

概括而言,如果将 WebSphere Application Server 配置为使用 Oracle JDBC 驱动程序进行连接级别的负载平衡,则 RAC 节点在任何实时 2PC 分布式事务(该事务跨多个 RAC 节点)的准备阶段出现故障时都需要数据库管理员手动干预。该数据库管理员必须完成孤立的事务分支,以释放这些事务分支所持有的数据库锁。对于数据库管理员来说,这是一个包括两个步骤的过程:

  1. 通过发出命令获取孤立的事务 ID,如:

    sql > select state, local_tran_ID, Global_tran_Id from dba_2pc_pending where state = "prepared";

  2. 然后回滚“准备”阶段中的所有事务 ID:

    sql > rollback force '<Global_tran_Id>';

处理 2PC 全局事务的正确 RAC 配置

手动干预不是事务恢复的首选方法;有些用户会选择自动而透明的事务恢复策略。透明恢复策略的关键是,对于任何全局事务,消除多个事务分支跨多个 RAC 节点;事务分支对应于全局事务中所用的数据库连接。如果一个全局 2PC 事务中的所有连接都源自同一 Oracle RAC 节点,就不会出现事务恢复问题。

下面简要介绍可以避免上述与 XA 相关的 Oracle RAC 限制的最简单策略:

  1. 创建一个 Oracle 分布式事务处理 (DTP) 服务(在 Oracle 10g R2 中引入,用于解决 Oracle 10g XA 的局限性);每项 DTP 服务都是一个单独的服务,可供一个(且只能是一个)Oracle RAC 实例使用。运行以下命令创建一个 DTP 服务:

    srvctl add service -d <dbname> -s <servicename> -r <primary nodes> -a <alternate nodes>

  2. 通过执行以下命令在 Oracle 服务上启用 DTP:

    execute dbms_service.modify_service (service_name => '<service_name>' , dtp => true);

  3. 确保每个 Oracle DTP 服务都配置为禁用负载平衡(即只有一个主服务)。

  4. 配置每个 WebSphere Application Server 集群成员,让其使用在步骤 1 中创建的 Oracle DTP 服务(图 3)。

    图 3. 配置集群以使用 DTP 服务
    图 3. 配置集群以使用 DTP 服务

该 DTP 服务将在首选实例上自动启动。不过,在数据库重启时,该 DTP 服务不会自动启动。您可以使用以下命令启动 DTP 服务:

srvctl start service -d <dbname> -s <service_name>

如果 RAC 节点停止工作,Oracle 需要在完成 Oracle RAC 清理和恢复之后才能对 DTP 服务进行故障转移。即使 Oracle 节点恢复,Oracle DTP 服务也不会返回到刚刚重启的 RAC 节点。相反,数据库管理员需要手动将该服务移动到重启的 RAC 节点。

图 4 描述了前面讨论的拓扑。

图 4. 示例场景拓扑
图 4. 示例场景拓扑

注意,从拓扑角度看,图 4 与图 2 一样。唯一的不同是对 Oracle DTP 服务的使用。与 URL (1)(在清单 1 中,其中所有的集群成员都有相同的数据源 URL)不同的是,这里的每个集群成员的数据源 URL 可能是唯一的,并且稍微不同于其他集群成员的数据源 URL。例如,对于瘦驱动程序而言,WebSphere Application Server 集群成员的数据源 URL 如下所示:

清单 2
jdbc:oracle:thin:@(DESCRIPTION= 
 (FAILOVER=on)
 (LOAD_BALANCE=off)
 (ADDRESS=(PROTOCOL=TCP)(HOST=rac-node1)(PORT=1521)) 
 (ADDRESS=(PROTOCOL=TCP)(HOST=rac-node2)(PORT=1521)) 
 (CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=<yourOraservice1toBeUsedForCluster1>))) (2)

and

jdbc:oracle:thin:@(DESCRIPTION= 
 (FAILOVER=on)
 (LOAD_BALANCE=off)
 (ADDRESS=(PROTOCOL=TCP)(HOST=rac-node2)(PORT=1521)) 
 (ADDRESS=(PROTOCOL=TCP)(HOST=rac-node1)(PORT=1521)) 
 (CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=<yourOraservice2toBeUsedForCluster2>))) (3)

对于胖驱动程序而言,URL 会非常类似:jdbc:oracle:oci 代替上述 URL 中的 jdbc:oracle:thin

当使用 Oracle 服务时,必须对 Oracle 服务定义本身指定负载平衡和故障转移,而不是在 URL 上指定。在使用 Oracle 服务时在 URL 中指定负载平衡或故障转移不会影响 RAC 节点的负载平衡或故障转移。但它会影响 Oracle 侦听器的负载平衡和故障转移。

在图 4 中,整个负载平衡都是在 WebSphere Application Server 级别通过路由器进行的。相关的 WebSphere 路由器维护事务关联,并且属于某项事务的所有请求都将被路由到同一 WebSphere 集群成员。由于 Oracle JDBC 驱动程序不提供任何负载平衡,所有这些入站请求都将打开并使用来自同一 RAC 节点的连接。这可防止任何 2PC 分布式事务跨多个 RAC 节点分布,因而可避免出现事务恢复问题。

由于一般的路由器配置会尝试跨所有的 WebSphere Application Server 集群成员统一分配请求,所以,如果未将每个 RAC 节点都配置为某个集群成员的主节点,则该数据库负载还会跨所有的 RAC 节点分发。如果适用,通过调整相关 WebSphere 路由器的静态权重(HTTP 和统一集群框架路由器的集群成员权重),WebSphere 系统管理员将能够在 RAC 节点之间的数据库负载分发中大致实现所期望的偏斜量。

在关闭负载平衡的情况下,有几点需要注意:

  • RAC 主节点和辅助节点将在数据源 URL 中按位置指定。
  • 可能会有多个辅助 RAC 节点。但是,只有一个 RAC 节点,即 URL 中 RAC 节点列表中第一个起作用的节点(如 (2))将用来获取物理连接。该节点可称为主要辅助节点。
  • 跨所有 RAC 节点实现统一数据库负载平衡的简单方法是满足以下两个条件:
    • 需要对适用的路由器进行相应配置,使所有 WebSphere 集群成员都可接收到相同比例的通信。
    • 应将每个 RAC 节点配置为可作为主节点,并可作为相同数量的 WebSphere 集群成员的主要辅助节点。在图 4 中,两个 RAC 节点都被配置为一个 WebSphere 集群成员的主节点和主要辅助节点(rac-node1 是 cluster-member1 的主节点,是 cluster-member2 的主要辅助节点;rac-node2 是 cluster-member2 的主节点,是 cluster-member1 的主要辅助节点)。

在 RAC 节点数量是 WebSphere 集群成员数的约数的情况下,上述条件很容易满足。


结束语

通过使用本文中介绍的“让 WebSphere Application Server 执行负载平衡”策略,可以使 WebSphere 集群环境更好地应对与事务恢复相关的问题。本文中演示的 URL 还可用于 WebSphere Process Server 环境,以便在出现 RAC 节点故障时自动而顺利地恢复 2PC 分布式事务。

主要-辅助 RAC 节点配置同样适用于独立的 WebSphere Application Server。但是,对于独立服务器,尽管 RAC 能够在连接级别提供故障转移,但却不能进行负载平衡。


本系列的其他文章

参考资料

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=WebSphere
ArticleID=283377
ArticleTitle=使用 WebSphere 中间件构建高可用性数据库环境,第 3 部分: 在 WebSphere Application Server 中使用 Oracle RAC 处理两阶段提交
publish-date=01282008