全部產品
Search
文件中心

ApsaraDB RDS:自動容錯移轉和讀寫分離

更新時間:Feb 28, 2024

使用PostgreSQL的libpq或JDBC,您可以通過簡單的配置實現自動容錯移轉(failover)和讀寫分離。

背景資訊

從PostgreSQL 10開始,libpq驅動層開始支援簡單的容錯移轉,JDBC驅動層則支援簡單的容錯移轉和負載平衡。

  • libpq是PostgreSQL的C應用程式介面,包含一組庫函數,允許用戶端程式將查詢請求發送給PostgreSQL後端伺服器並接收這些查詢的結果。

  • JDBC(Java Database Connectivity)是Java語言中用來規範用戶端程式如何訪問資料庫的應用程式介面,在PostgreSQL中JDBC支援容錯移轉和Server Load Balancer(Load Balance)。

libpq實現自動容錯移轉和讀寫分離

通過libpq函數串連多個資料庫,當出現故障時會自動切換到可用的資料庫。

命令

postgresql://[user[:password]@][netloc][:port][,...][/dbname][?param1=value1&...]

樣本

如下樣本為串連1個RDS PostgreSQL主執行個體資料庫和對應的2個唯讀執行個體資料庫,只要確保至少有一個資料庫可用,讀請求就不會失敗。

postgres://pgm-bpxxx1.pg.rds.aliyuncs.com:3433,pgm-bpxxx2.pg.rds.aliyuncs.com:3433,pgm-bpxxx3.pg.rds.aliyuncs.com:3433/postgres?target_session_attrs=any

target_session_attrs表示允許串連到指定狀態的資料庫,取值:

  • any:預設值,表示允許串連到任意資料庫,會從所有配置的資料庫中隨機播放一個嘗試串連,如果串連的資料庫出現故障導致串連斷開,會嘗試串連其他資料庫,從而實現容錯移轉。

  • read-write:只會串連到支援讀寫的資料庫,即從第一個資料庫開始嘗試串連,如果串連後發現不支援讀寫,則會中斷連線,然後嘗試串連第二個資料庫,以此類推,直至串連到支援讀寫的資料庫。

更多libpq的使用方法和參數說明請參見Connection Strings

您可以在應用程式中結合pg_is_in_recovery()函數,判斷串連的資料庫是主執行個體資料庫的還是唯讀執行個體資料庫,最終實現讀寫分離和容錯移轉,樣本如下:

  • Python樣本

    $ cat pg_conn.py
    import psycopg2
    conn = psycopg2.connect(database="postgres",host="pgm-bpxxx1.pg.rds.aliyuncs.com,pgm-bpxxx2.pg.rds.aliyuncs.com,pgm-bpxxx3.pg.rds.aliyuncs.com", user="testxxx", password="xxxxxx", port="3433", target_session_attrs="read-write")
    cur = conn.cursor()
    cur.execute("select pg_is_in_recovery(), pg_postmaster_start_time()")
    row = cur.fetchone()
    print "recovery =",row[0]
    print "time =",row[1]
    
    $ python pg_conn.py
    recovery = False
    time = 2020-07-09 15:33:57.79001+08
    說明

    上述樣本中的print文法僅適用於Python 2,如使用的Python版本為Python 3,請將print部分修改為如下內容:

    print("recovery =", row[0])
    print("time =", row[1])

  • PHP樣本

    # cat pg_conn.php  
    <?php  
    $conn = pg_connect("host=pgm-bpxxx1.pg.rds.aliyuncs.com,pgm-bpxxx2.pg.rds.aliyuncs.com,pgm-bpxxx3.pg.rds.aliyuncs.com port=3433 dbname=postgres user=testxxx password=xxxxxx target_session_attrs=read-write") or die("Could not connect");  
    $status = pg_connection_status($conn);  
    if ($status === PGSQL_CONNECTION_OK) {  
    print "Connection status ok\n";  
    } else {  
    print "Connection status bad\n";  
    }  
    $sql = pg_query($conn, "select pg_is_in_recovery()");  
    while ($row = pg_fetch_row($sql)) {  
    echo "Recovery-status: $row[0]\n";  
    }  
    ?>  
    
    $ php -f pg_conn.php  
    Connection status ok  
    Recovery-status: f  
    Server: xxx.xxx.xx.xx  

JDBC實現讀寫分離和自動容錯移轉

您可以在串連URL中定義多個資料庫,並用逗號分隔,驅動程式將嘗試按順序串連到它們中的每一個,直到串連成功。如果沒有成功,會返回串連異常報錯。

命令

jdbc:postgresql://node1,node2,node3/accounting?targetServerType=preferSlave&loadBalanceHosts=true  

樣本

jdbc:postgresql://pgm-bpxxx1.pg.rds.aliyuncs.com:3433,pgm-bpxxx2.pg.rds.aliyuncs.com:3433,pgm-bpxxx3.pg.rds.aliyuncs.com:3433/accounting?targetServerType=preferSlave&loadBalanceHosts=true  

參數說明如下:

  • targetServerType表示允許串連到指定狀態的資料庫,取值:

    • any:任何資料庫。

    • master:主要資料庫。

    • slave:從資料庫。

    • preferSlave:優先從資料庫,如果沒有從資料庫才串連到主要資料庫。

    說明

    區別資料庫主從的方式是通過查詢資料庫是否允許寫入,允許寫入的判斷為主要資料庫,不允許寫入的判斷為從資料庫。

  • loadBalanceHosts表示嘗試串連資料庫的順序,取值:

    • False:預設值,按命令內順序串連資料庫。

    • True:隨機串連資料庫。

為實現讀寫分離,您需要在配置JDBC時配置2個資料來源,1個設定targetServerType=master,一個設定targetServerType=preferSlave。需要寫操作時,指定master的資料來源,需要讀操作時,指定preferSlave的資料來源。如果需要判斷資料來源類型,您可以結合pg_is_in_recovery()函數,判斷串連的資料庫是主執行個體資料庫的還是唯讀執行個體資料庫,最終實現讀寫分離和容錯移轉。