2022年2月14日 星期一

9. Load Balance 與 Failover

RAC 是由多個 Server 所組成,當其中一個節點發生故障時,還有其它的節點可以提供服務,這個特性我們將其稱為 Failover ;當我們透過 SQL*Net 連線到 RAC 資料庫時, RAC 會自動將這些連線平均的分配到每一個擁有此 Database Instance 的節點上,這個特性我們稱作為 Load Balance 。


RAC 資料庫的連線方式可以透過 vip 直接連線或者是使用 SCAN ,透過 vip 連線如果想要達到 Load Balance 的效果,必須把每個節點的 vip 設定到 tnsnames.ora 並使用 LOAD_BALANCE=ON ,這樣系統就會平均將連線分散到每個節點上;如果是使用 SCAN-NAME 連線,那麼就會先去 DNS 查詢此 SCAN-NAME 所對應的 IP ,然後由 SCAN Listener 接收到連線的資訊,最後再將連線平均分配到每個節點上。


RAC 的 Load Balance 可以分為 Client Side Load Balance 與 Server Side Load Balance 兩種:


  • Client Side Load Balance : 透過 tnsnames.ora 的 LOAD_BALANCE=ON 設定所實現,例如:


ORCL=

(DESCRIPTION=

    (ADDRESS_LIST=

      (LOAD_BALANCE=ON)

      (ADDRESS=(PROTOCOL=TCP)(HOST=node1-vip)(PORT=1521))

      (ADDRESS=(PROTOCOL=TCP)(HOST=node2-vip)(PORT=1521)))

    (CONNECT_DATA=(SERVICE_NAME=ORCL)))


這樣連線到 ORCL 時就會隨機使用 node1-vip 或 node2-vip 進行連線,如果不使用 LOAD_BALANCE=ON ,那麼只會先使用第一組 node1-vip 進行連線,同樣的設定也適用於 scan ip :


ORCL=

(DESCRIPTION=

    (ADDRESS_LIST=

      (LOAD_BALANCE=ON)

      (ADDRESS=(PROTOCOL=TCP)(HOST=192.168.49.110)(PORT=1521))

      (ADDRESS=(PROTOCOL=TCP)(HOST=192.168.49.111)(PORT=1521))

      (ADDRESS=(PROTOCOL=TCP)(HOST=192.168.49.112)(PORT=1521)))

    (CONNECT_DATA=(SERVICE_NAME=ORCL)))


192.168.49.110 ~ 112 這三組是 SCAN-NAME 註冊到 DNS 上所對應的三組 IP 。以上兩種設定都可以達到 Client Side Load Balance 的效果。


  • Server Side Load Balance : tnsnames.ora 裡面不使用 LOAD_BALANCE=ON ,而是透過資料庫參數的 remote_listener 來實現,也就是說先連線到某一個節點上,然後再經由 remote_listener 來平均分配連線。 remote_listener 的設定可以使用 vip 或者是 SCAN-NAME ,在 Grid Infrastructure 的架構下, remote_listener 預設都是為 SCAN-NAME 。如果要使用 vip 來達成 Server Side Load Balance ,首先必須於 tnsnames.ora 定義 remote_listener 所對應的 vip 資訊:


LISTENER_REMOTE =

  (ADDRESS_LIST =

    (ADDRESS = (PROTOCOL = TCP)(HOST = node1-vip)(PORT = 1521))

    (ADDRESS = (PROTOCOL = TCP)(HOST = node2-vip)(PORT = 1521)))


定義好之後將參數 remote_listener 設定為此:


SQL> alter system set remote_listener='LISTENER_REMOTE';


設定好之後,資料庫的連線字串就不需要使用 LOAD_BALANCE=ON :


ORCL=

(DESCRIPTION=

    (ADDRESS_LIST=

      (ADDRESS=(PROTOCOL=TCP)(HOST=node1-vip)(PORT=1521))

      (ADDRESS=(PROTOCOL=TCP)(HOST=node2-vip)(PORT=1521)))

    (CONNECT_DATA=(SERVICE_NAME=ORCL)))


如果是使用 SCAN-NAME 來連線,那麼連線字串就簡單使用 SCAN-NAME 再搭配 remote_listener 就可以達到 Server Side Load Balance 的效果:


SQL> alter system set remote_listener='SCAN-NAME:1521'


ORCL=

(DESCRIPTION=

    (ADDRESS_LIST=

      (ADDRESS=(PROTOCOL=TCP)(HOST=SCAN-NAME)(PORT=1521)))

    (CONNECT_DATA=(SERVICE_NAME=ORCL)))


至於 Failover 的類型可以分為 Client-Side Connect Time Failover 、 Transparent Application Failover (TAF) 與 Sever-Side TAF 三種 :


  • Client-Side Connect Time Failover : 在連線的階段進行 Failover ,透過 tnsnames.ora 的 FAILOVER=ON 設定所實現,例如:


ORCL=

(DESCRIPTION=

    (ADDRESS_LIST=

      (FAILOVER=ON)

      (ADDRESS=(PROTOCOL=TCP)(HOST=node1-vip)(PORT=1521))

      (ADDRESS=(PROTOCOL=TCP)(HOST=node2-vip)(PORT=1521)))

    (CONNECT_DATA=(SERVICE_NAME=ORCL)))


這個設定當中由於沒有 LOAD_BALANCE=ON ,所以會優先使用第一個 ip ,也就是 node1-vip 進行連線,由於設定了 FAILOVER=ON ,當 node1-vip 無法連線時,就會自動改用 node2-vip 來嘗試連線。


  • Transparent Application Failover : 已經成功連進資料庫並進行作業的時候,若當前的節點發生問題,則自動將 session 轉移到另一個節點上繼續作業,透過 tnsname.ora 的 FAILOVER_MODE 設定來實現,例如:


ORCL=

(DESCRIPTION=

    (ADDRESS_LIST=

      (LOAD_BALANCE=ON)

      (ADDRESS=(PROTOCOL=TCP)(HOST=node1-vip)(PORT=1521))

      (ADDRESS=(PROTOCOL=TCP)(HOST=node2-vip)(PORT=1521)))

    (CONNECT_DATA=(SERVICE_NAME=ORCL)

    (FAILOVER_MODE =

               (TYPE=SELECT)

               (METHOD=BASIC)

               (RETRIES=180)

               (DELAY=5))))


FAILOVER_MODE 共有四個參數可做設定:


  • TYPE : 可設定為 session 或者是 select 。 session - 當節點發生問題時, Client 必須要重新連線; select – 當節點發生問題時,自動將當前的 session 導向另一個節點,此時連線不會中斷。

  • METHOD : 可設定為 basic 或者是 preconnect 。 basic – 當前節點發生問題時才會連線到另一個節點上。 preconnect – 除了當前節點的連線外,同時也建立 shadow connect 到其它節點上。

  • RETRIES : 用來設定 failover 的重新嘗試次數。

  • DELAY : 用來設定重新嘗試的間隔時間,以秒為單位。


這邊要注意的是,只有在做 select 行為時的 failover 連線才不會中斷,如果是 DML 的行為,那麼當前的 session 就會中斷,必須重新連線才行。


透過 v$session 可以查詢此 session 是否被 failover :


ORCL=

SQL> select username,service_name,failover_method,failover_type

      from v$session where sid = 1170;


USERNAME     SERVICE_NAME    FAILOVER_METHOD    FAILOVER_TYPE

---------------    ---------------------   ---------------------------    -----------------------

  SCOTT          ORCL            BASIC                SESSION


  • Server-Side TAF : 透過 Oracle Service 所實現,當我們建立好一個資料庫時,預設會產生以 db_unique_name 為名稱的 service ,除此之外,我們還可以針對此資料庫建立其它的 service 來使用。在 RAC 架構中,建立額外的 DB Service 可以用來將工作群組化,例如一組四個節點的 RAC ,此時可以建立兩個 Service , Service A 只啟用在 node1 與 node2 、 Service B 則啟用在 node3 與 node4 ,此時所有的交易型作業都使用 Service A 來連線,那麼交易就只會使用到 node1 與 node2 、 批次型的作業則是使用 Service B 連線,則批次作業就只會跑在 node3 與 node4 ,工作群組化的好處是,可以將每個 RAC 節點所需要扮演的角色定義清楚,各司其職,避免一個節點同時執行太多不同種類的作業,增加系統的負擔。


建立 Service 的另一個好處是可以達到 TAF 的效果,例如建立一個 Service C ,那麼此時可以設定 Service C 主要只啟用在 node1 而 node2 則是當備援,當 node1 發生問題時再把 Service C 導向 node2 繼續進行服務。


在 RAC 架構中,以 srvctl 指令來建立 Service ,若是 single instance 的架構,則是使用 dbms_service 來建立。在 RAC 節點為 Administrator Managed 的情況下, Service 可以設定 Preferred Server (將 Service 啟用在哪些節點) 以及 Available Server (將哪些節點作為此 Service 的備援) ,例如建立一個 orcl_job 的 Service :


$ srvctl add service –d orcl –s orcl_job –r node1 –a node2 –e select –z 10 –w 5


-d : 針對哪一個資料庫來建立它的 Service 

-s : Service 名稱,在此為 orcl_job 

-r : Preferred Server

-a : Available Server

-e : TAF failover type ,在此為 select

-z : TAF retry 次數

-w : TAF retry 間隔時間


這邊設定了 Preferred Server 為 node1 、 Available Server 為 node2 ,表示 orcl_job 這個 Service 只運行在 node1 ,當 node1 發生故障時再把 Service 轉移到 node2 進行服務。


在 Policy Managed 的架構下,則是設定此 Service 為 Uniform (Server Pool 中的所有節點都啟用此 Service) 或是 Singleton (只將此 Service 啟用在此 Server Pool 中的一個節點上) ,例如:


$ srvctl add service –d orcl –s orcl_job –g SP1 –c uniform –e select –z 10 –w 5


-g : Server Pool 的名稱,在此為 SP1

-c : 設定 Service 啟用的節點,在此為 uniform


建立好 Service 之後便可透過 srvctl 來操作:

$ srvctl start service –d orcl –s orcl_job

  (開啟 orcl_job 這個 service 服務)

$ srvctl stop service –d orcl –s orcl_job

  (關閉 orcl_job 這個 service 服務)

$ srvctl modify service –d orcl –s orcl_job –i node2 –r

  (將 node2 設定為 orcl_job 這個 service 的 preferred server)

$ srvctl relocate service –d orcl –s orcl_job –i node1 –t node2

  (將 orcl_job 這個 service 從 node1 移轉到 node2)

$ srvctl remove service –d orcl –s orcl_job

  (刪除 orcl_job 這個 service)


Load Balance 與 Failover 這兩個功能是 RAC 架構下的特性,不過 Load Balance 功能算是一個雙面刃,好處是可以將連線平均分配到所有節點上達到均衡負載的效果,缺點是資料庫容易產生 GC (Global Cache) 的等待事件,有時候 GC 事件對於效能來說會產生重大影響,比較好的做法是使用 Service ,利用 Service 將作業分配到指定的節點上運行,用指定節點的方式來運行不僅可以達到負載平衡的目的,同時由於作業類型的不同也可以避免 GC 等待事件的產生,再加上 Service 也具有 TAF 的特性,不用擔心會單點故障,使用 Service 可以說是一舉數得。



沒有留言:

張貼留言