详解 RAC 中各种IP和监听的意义
一、SCAN 概念
SCAN(Single Client Access Name)是 Oracle从11g R2开始推出的,客户端可以通过 SCAN 特性负载均衡地连接到 RAC数据库
SCAN 最明显的优点就是,当集群中新增加了节点或者删除了节点,不需要额外维护客户端
查看 SCAN 的配置信息的方式如下:
[grid@rac2 ~]$ srvctl config scan
SCAN name: rac-scan, Network: 1/192.168.56.0/255.255.255.0/bond0
SCAN VIP name: scan1, IP: /rac-scan/192.168.56.90
查看 SCAN VIP 的状态:可以发现 SCAN VIP 运行在节点 rac2
[grid@rac2 ~]$ srvctl status scan
SCAN VIP scan1 is enabled
SCAN VIP scan1 is running on node rac2
二、IP 概念
RAC 中有很多种 IP,每种 IP 的作用分别是什么呢?
Public IP:
- 这是网卡上配置的真实IP地址,我们称为公共IP,这个IP的存在关系到 VIP 能不能正确漂在其所在网卡上
- 注意,PUBLIC IP是不提供给客户端去连接配置的,这并不是说通过 PUBLIC IP 无法连接实例,而是当节点服务器宕机时,所有向它请求连接的客户端都会有等待现象并且最后得到超时信息
Private IP:
- 称为私网 IP(私有IP),它是用于心跳同步的,也就是保证两台服务器数据同步
- Oracle另一个高可用性连接特性(HAIP)
- 其实 Cache Fusion 会消耗节点服务器很大的私网资源,另外,私网间无法通信还会引起 brain split(脑裂),以前为解决这种问题,我们可以采用网卡 bonding 技术,而 Oracle 在 11g R2 的时候通过 HAIP 技术来实现
- HAIP(Highly Available Virtual IP)用于节点间的私网通信,支持同时使用多个网络连接来满足网卡间的负载均衡,并且还提高了Cache Fusion 资源通信能力
Virtual IP:
- RAC 的每个节点都需要有一个虚拟IP,这就是VIP
- VIP 会绑定到节点的 public 网卡上,需要和 PUBLIC IP同一个子网,它们是由 GI 的 Clusterware 来管理的
- VIP 在其节点服务器发生故障的时候会自动漂移到另外正常的节点服务器上,如果 RAC 是多节点运行的,那具体漂移到哪个活动的节点将由Clusterware 决定
- 等故障节点恢复正常,漂移的 VIP 也回到此节点上,继续提供服务
三、监听概念
下面再解释一下 RAC 中监听的概念
LOCAL LISTENER:
- 本地监听,RAC 的每个节点上都会有独立的本地监听,它会监听该节点的 PUBLIC IP和VIP
- 每个节点的实例在启动的时候向本地监听进行注册,当 VIP 或者PUBLIC IP (这种情况比较少见)有连接请求的时候,本地监听就接受处理并和本地实例建立连接。如果某个节点故障,其上面的VIP会进行漂移,但本地监听并不会产生漂移
SCAN LISTENER:
- SCAN 监听,它是实现 SCAN 负载均衡的原理所在
- SCAN 监听跟着 SCAN VIP 随机分配到节点服务器上,如果某个节点发生故障,运行在此节点上的 SCAN VIP 会进行漂移,这时候 SCAN 监听也跟着漂移到正常的节点上,继续为 SCAN VIP 监听连接请求,当 PMON 进程下次动态更新实例信息到该 SCAN 监听后,它又重新接受客户端的连接
查看 SCAN 监听的配置和状态:
[grid@rac2 ~]$ srvctl config scan_listener
SCAN Listener LISTENER_SCAN1 exists. Port: TCP:1521
[grid@rac2 ~]$ srvctl status scan_listener
SCAN Listener LISTENER_SCAN1 is enabled
SCAN listener LISTENER_SCAN1 is running on node rac2
1、local_listener 参数
该参数控制着本地监听的注册,通过本地监听的数据库连接请求只会连接到本地节点的实例上
数据库中,该参数设置为向本地 VIP 地址进行注册:
SQL> show parameter local
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
local_listener string (ADDRESS=(PROTOCOL=TCP)(HOST=
192.168.56.80)(PORT=1521))
查看本地监听的状态,可以发现本地监听在 Public IP 和 VIP 上监听,只监听本地实例:
[grid@rac2 ~]$ lsnrctl status listener
Listening Endpoints Summary...
(DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=LISTENER)))
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.56.20)(PORT=1521)))
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.56.80)(PORT=1521)))
Services Summary...
Service "+ASM" has 1 instance(s).
Instance "+ASM2", status READY, has 1 handler(s) for this service...
Service "rac" has 1 instance(s).
Instance "rac2", status READY, has 1 handler(s) for this service...
Service "racXDB" has 1 instance(s).
Instance "rac2", status READY, has 1 handler(s) for this service...
2、remote_listener 参数
该参数控制 SCAN 监听的注册,每个节点上都设置,这样的话,每个节点的 PMON 都会向 SCAN 监听注册实例信息,所以 SCAN监听能够负载均衡地分发连接请求到节点本地监听上,也就是连接到其本地节点实例上
示例:
SQL> show parameter remote_listener
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
remote_listener string rac-scan:1521
查看 SCAN 监听的状态,可以发现它监听了所有实例:
[grid@rac2 ~]$ lsnrctl status listener_scan1
Listening Endpoints Summary...
(DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=LISTENER_SCAN1)))
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.56.90)(PORT=1521)))
Services Summary...
Service "rac" has 2 instance(s).
Instance "rac1", status READY, has 1 handler(s) for this service...
Instance "rac2", status READY, has 1 handler(s) for this service...
Service "racXDB" has 2 instance(s).
Instance "rac1", status READY, has 1 handler(s) for this service...
Instance "rac2", status READY, has 1 handler(s) for this service...
3、修改 remote_listener 参数
通过 remote_listener
的修改,让 SCAN 以及所有节点的本地监听都可以监听到所有数据库实例
第一步,在节点 rac1 的 tnsnames.ora
文件中配置 tnsnames,使该节点可以被 rac2 的 listener 监听到:
[oracle@rac1 admin]$ pwd
/u01/app/oracle/product/11.2.0/db_1/network/admin
[oracle@rac1 admin]$ vim tnsnames.ora
RAC =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = rac-scan)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = rac2-vip)(PORT = 1521))
(LOAD_BALANCE = yes)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = rac)
)
)
在节点 rac2 的 tnsnames.ora
文件中配置 tnsnames,使该节点可以被 rac1 的 listener 监听到:
RAC =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = rac-scan)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = rac1-vip)(PORT = 1521))
(LOAD_BALANCE = yes)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = rac)
)
)
第二步,修改 remote_listener
参数(在其中一个节点操作即可):
SQL> alter system set remote_listener=rac;
System altered.
第三步,查看 LISTENER 监听状态,可以监控到所有的数据库实例
[grid@rac1 admin]$ lsnrctl status
Listening Endpoints Summary...
(DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=LISTENER)))
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.56.10)(PORT=1521)))
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.56.60)(PORT=1521)))
Services Summary...
Service "+ASM" has 1 instance(s).
Instance "+ASM1", status READY, has 1 handler(s) for this service...
Service "rac" has 2 instance(s).
Instance "rac1", status READY, has 1 handler(s) for this service...
Instance "rac2", status READY, has 1 handler(s) for this service...
Service "racXDB" has 2 instance(s).
Instance "rac1", status READY, has 1 handler(s) for this service...
Instance "rac2", status READY, has 1 handler(s) for this service...
第四步,查看 SCAN 监听状态,可以监控到所有的数据库实例(需要先查看 SCAN 监听在哪个节点)
[grid@rac1 ~]$ lsnrctl status listener_scan1
Listening Endpoints Summary...
(DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=LISTENER_SCAN1)))
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.56.90)(PORT=1521)))
Services Summary...
Service "rac" has 2 instance(s).
Instance "rac1", status READY, has 1 handler(s) for this service...
Instance "rac2", status READY, has 1 handler(s) for this service...
Service "racXDB" has 2 instance(s).
Instance "rac1", status READY, has 1 handler(s) for this service...
Instance "rac2", status READY, has 1 handler(s) for this service...