昨天晚上,新晋ACED熊军在云和恩墨大讲堂微信群中分享了一个主题:RAC数据库load balance。下面是详细的内容整理:
熊军(老熊)
云和恩墨西区总经理
Oracle ACED,ACOUG核心会员
今天非常高兴能与大家分享一下Oracle RAC数据库的技术经验。今天我将通过两个案例入手,来讲一下RAC数据库load balance相关的问题。
两个案例会以比较直接简单的方式进行描述,对于案例中涉及到的深入的知识将在后面展开。
一套2节点的Oracle 10g RAC数据库。系统维护人员报告称不能实现负载均衡,大部分的会话都连接到了第二个节点上。
Oracle 10.2.0.3 for AIX
①连接到数据库,检查数据库连接,发现实例resrac2的连接数超过2000,而实例resrac1的连接数不到300。相差非常大。
②检查2个节点的监听状态,没有异常。
可以看到resrac服务配置正常。
上面的数据可以看出第1个实例resrac1存在问题。实例resrac2的goodness值与以resrac服务连接的连接数是接近相等的(这跟更新的周期有关)。但实例resrac1的goodness值远远大于resrac1的实际连接数。
检查MMON进程没有发现异常。
⑪从上面的分析可以看到,Service Metric的数据异常,导致了实例resrac1不能接受新的连接。由于resrac1实例的resrac服务的goodness值异常地高,怀疑是BUG引起。
⑫搜索Oracle的BUG数据库,发现与下面的BUG匹配
但是当前的版本没有此BUG的补丁,只有升级到10.2.0.4才能解决。
重启实例resrac1,但是以后BUG可能被再次触发
将Oracle数据库升级到10.2.0.4
关闭服务端(Server Side)的Load balancing,修改应用的连接配置,使用客户端连接时负载均衡(Connection Time Load Balancing)
一套2节点的Oracle 11g RAC Active Data Guard,应用通过SCAN 地址连接到数据库,绝大部分连接都连到了节点1上。
某银行重要交易系统,Oracle 11.2.0.4 for Linux,2节点RAC主库+2节点本地RAC ADG+2节点同城异机房RAC ADG,读写分离架构,ADG用于只读查询,主库实现事务交易,分布式存储架构,同城异机房实现容灾。SCAN地址通过域名解析。
BTW:比较新潮的架构模式,去I、E,读写分离,ADG容灾。
分析过程与思路与前面一致。关键的差异在于:
①Active Data Guard指定与主库不同的db_unique_name,那么默认注册到监听的服务与db_unique_name是一致的。但是这个服务名通过dba_services视图查询并没有。
②查询v$servicemetric视图也没有这个服务的统计数据。
那么,会不会是因为pmon不能发布服务的负载信息呢?好在有这样一个事件10257。
在pmon的trace文件中不断重复出现这样的信息:
我们需要有点耐心,一会儿会出现:
如果我们手工执行alter system register命令,会有这样的日志:
应用连的服务名是“cusrdg”,很显然这个并不在里面。
好在有一套测试环境,同样的架构。在测试环境中,使用ADG的db_unique_name指定的服务,同样不能达到负载均衡。但是如果用dbms_service.add_service增加一个服务(需要在主库上操作),然后在备库启用这个服务,使用这个服务则是可以正常进行负载均衡。
将上述脚本在后台跑上几十个,检查gv$session就可以发现负载均衡是否起作用。
我们在测试ADG库上看到的10257 event trace的输出有:
可以看到有drtestsvc这个单独建的服务名,这个服务名出现在pmon向监听注册的信息中。
负载均衡分两种:Client Side Load Balance和Server Side Load Balance。
客户端的负载均衡通过连接描述符来指定:
要实现LOAD BALANCE,不能指定INSTANCE_NAME,也不能指定SID,连接时“面向服务”。
客户端连接描述符在指定多个地址还默认打开了failover,也就是一个地址连接不上就会连接另一个地址。
服务器端的负载均衡,又是怎么一种机制呢?
10g和11g有很大的不同,这里以11g RAC为例来解释:
我们配合监听的信息来展示一下(这是在第2个节点上获得的信息):
VIP监听信息:
打开数据库后,pmon进程会向监听注册服务:
remote_listener指向SCAN LISTENER, local_listener指向本节点VIP监听。这里有一个PORT为1522的是一个单独的监听,这里先忽略。
我们会看到,VIP监听上的服务只有一个实例,即本节点的实例的服务。
但是SCAN监听上有两个实例,第2个实例是:
REMOTE SERVER只是表示说,这个实例是需要通过另一个监听来跳转,这个监听不能直接连接到该实例上,对于SCAN监听,所有的实例都是远程实例。
那么REMOTE SERVER中的信息是从哪里来,实际上是PMON进程将local listener的信息告诉SCAN监听。大家可以看到local listener设定的信息跟SCAN LISTENER中Remote Server的信息是一样的。
OK,下面来看一下如何实例负载均衡,客户端与数据库的交互顺序是这样的:
1) 客户端连接到SCAN监听。
2) SCAN监听根据客户端连接时指定的条件(SERVICE_NAME),选择一个实例。
3) SCAN监听把选定的实例的信息,包括地址,端口,协议,实例名发给客户端。
4) 客户端根据这个信息,重新发起一次网络连接,这次连接到实例的VIP监听上,VIP监听的服务是LOCAL SERVER,所以它会建立真正的连接。
5) 接下来就是登录验证。
这个过程中的两个个关键点:
1) 上述第2步的实例选择,监听是从PMON得到的实例的负载信息,来选择一个实例,这一步实现了负载均衡。
如果连接SCAN时,指定了INSTANCE NAME参数,那SCAN监听只会重定向到指定参数。
2) 如果local listener参数设置不对(正常情况下,11g不需要显式设置,由Grid Infrastructure设置好就行),那么将不能连接,会报错。这个参数正常指向VIP地址,如果设置为主机名或域名,但是客户端不能解析,就连接不上。
到这里,会有一个跟网络安全相关的话题,有的企业的应用是在另外的网络,中间有网闸或NAT,连接SCAN监听时,用的一个外网地址,外网地址通过NAT转换,得到内网的地址。
比如,外网是10.10.100.144:1521,内网是192.168.100.144:1521,有一个NAT设备进行转换。
SCAN监听会返回一个VIP监听地址,不幸的是,它会返回内网local listener地址。比如192.168.100.141:1521,客户端在外网连接这个地址肯定是不通的。
那是否可以将数据库的参数设置为外网地址呢?这样的话它就注册不到vip 监听上了。这也是有问题。
这样的方式下,用客户端的负载均衡,直接连接VIP地址是更好的选择。
另外,一些比较老的JDBC驱动,不能识别SCAN监听发回的要求重定向的协议,这种驱动连接数据库也有问题。
在监听的信息中,会有这样的信息:
表示接受这个服务的处理器(实例)的状态ready,已经拒绝多少个连接,建立了多少连接。
显然这个应用没有连接SCAN监听,因为这个监听的所有服务的连接数都是0.
只有本地的VIP监听才显示了有连接。
另外,在VIP监听日志中:
这表示直接连接或本机SCANLISTENER连接的。
如果有INSTANCE_NAME=这样的字样,则表示是另一个节点转发过来的。
我们去检查监听日志,可以查看这个有用的信息。
grep “service update” listener.log
grepINSTANCE_NAME= listener.log
如果有这样的数据,表明客户端连接指定了INSTANCE_NAME,这个可能是连接串指定了(当前这种很少)。对于负载均衡来说,更多的是客户端开始连接到另外节点的SCAN LISTENER上然后重定向过来的。
最后有3个小问题,留待大家去发掘:
1) 中间件也有自己的负载均衡连接池或数据源。跟ORACLE的机制无关。
2) Oracle自己的连接池驱动,可以快速地感知,数据库节点的变化,比如宕掉、重新启动了,然后自动进行选择和处理,这是如何实现的。
3) Oracle 12c中的Global Data Services。
恩墨学院