openGauss Cluster Manager RTO Test

語言: CN / TW / HK

目錄

一、環境介紹

1. 軟件環境

2. 硬件環境

3. 架構圖

二、測試場景

1. go程序多IP連接測試RTO

2. BenchmarkSQL多IP連接測試RTO

3. 數據庫端觀測時間

總結

 


 

一、環境介紹

1. 軟件環境

類別 版本 下載鏈接 備註
OS openEuler 20.03 (LTS) http://repo.openeuler.org/openEuler-20.03-LTS/ISO/aarch64/openEuler-20.03-LTS-aarch64-dvd.iso 操作系統
BenchmarkSQL 5.0 Download BenchmarkSQL from SourceForge.net
驅動版本:postgresql-9.3-1102.jdbc41.jar
模擬TPCC壓力的程序
驅動為程序自帶的pg驅動
Golang go1.18 linux/arm64 http://golang.google.cn/dl/go1.18.1.linux-arm64.tar.gz 
example/multi_ip/multi_ip.go · openGauss/openGauss-connector-go-pq - Gitee.com 
openGauss-connector-go-pq 標籤 - Gitee.com
模擬應用連接的程序
openGauss 3.0.0 http://opengauss.obs.cn-south-1.myhuaweicloud.com/3.0.0/arm/openGauss-3.0.0-openEuler-64bit-all.tar.gz 數據庫

2. 硬件環境

主機 CPU 規格 硬盤 職責
node1 Kunpeng-920虛擬機 16c/64g 通用型SSD 主庫
node2 Kunpeng-920虛擬機 16c/64g 通用型SSD 同步備庫
go程序        
node3 Kunpeng-920虛擬機 16c/64g 通用型SSD 異步備庫BenchmarkSQL程序

3. 架構圖

二、測試場景

1. go程序多IP連接測試RTO

原理:CM檢測主庫發生故障,不可訪問時會自動選新主,go驅動通過target_session_attrs=read-write控制只連主庫,通過SQL
select sysdate,pg_is_in_recovery(); 查詢結果時間戳查看RTO

  • go程序代碼
[root@cloud001-0003 go]# cat 1.go 
// Copyright © 2021 Bin Liu <[email protected]>

package main

import (
        "database/sql"
        "fmt"
        _ "gitee.com/opengauss/openGauss-connector-go-pq"
        "log"
        "os"
        "os/signal"
        "syscall"
        "time"
)

/*
需要有訪問dbe_perf.global_instance_time的權限
CREATE USER dbuser_monitor with login monadmin PASSWORD 'Mon@1234';
grant usage on schema dbe_perf to dbuser_monitor;
grant select on dbe_perf.global_instance_time to dbuser_monitor;
CGO_ENABLED=0 GOOS=linux GOARCH=arm64
*/

var (
        dsnExample = `DSN="postgres://gaussdb:secret@foo,bar,baz/mydb?sslmode=disable"
DSN="postgres://gaussdb:secret@foo:1,bar:2,baz:3/mydb?sslmode=disable"
DSN="user=gaussdb password=secret host=foo,bar,baz port=5432 dbname=mydb sslmode=disable"
DSN="user=gaussdb password=secret host=foo,bar,baz port=5432,5432,5433 dbname=mydb sslmode=disable"`
)

func main() {
 os.Setenv("DSN", "postgres://gaussdb:[email protected]:26000,172.16.0.202:26000,172.16.0.193:26000/postgres?"+
"sslmode=disable&loggerLevel=debug&target_session_attrs=read-write")
        connStr := os.Getenv("DSN")
        if connStr == "" {
                fmt.Println("please define the env DSN. example:\n" + dsnExample)
                return
        }
        fmt.Println("DNS:", connStr)
        db, err := sql.Open("opengauss", connStr)
        if err != nil {
                log.Fatal(err)
        }
        var (
                newTimer = time.NewTicker(1 * time.Second)
                doClose  = make(chan struct{}, 1)
        )

        go func() {
                for {
                        select {
                        case <-newTimer.C:
                                if err := getNodeName(db); err != nil {
                                        fmt.Println(err)
                                }
                        case <-doClose:
                                newTimer.Stop()
                                return
                        }
                }
        }()

        sigChan := make(chan os.Signal, 2)
        signal.Notify(sigChan, syscall.SIGTERM, syscall.SIGINT, syscall.SIGKILL) //nolint:staticcheck
        defer signal.Stop(sigChan)
        <-sigChan
        doClose <- struct{}{}

}

func getNodeName(db *sql.DB) error {
        var err error
        // tx, err := db.Begin()
        // if err != nil {
        //      return err
        // }
        // defer tx.Commit()
        var sysdate string
        var pgIsInRecovery bool
        var nodeName string
        err = db.QueryRow("select sysdate,pg_is_in_recovery();").
                Scan(&sysdate, &pgIsInRecovery)
        if err != nil {
                return err
        }
        var channel string

        // err = db.QueryRow("select channel from pg_stat_get_wal_senders() limit 1 ").
        //      Scan(&channel)
        fmt.Println(sysdate, nodeName, pgIsInRecovery, channel)
        // if err != nil {
        //      return err
        // }
        return nil
}


  • 模擬數據庫故障
[omm@cloud001-0002 data]$ mv db1/ db1.bak
  • go程序連接數據庫及重連時間

  • 時間差
2022/04/11 16:02:13.614273 connector.go:222:  info dialing server host 172.16.0.65 port 26000 
2022/04/11 16:02:20.683716 connector.go:145: debug find instance host 172.16.0.202 port 26000 

RTO時間7s

2. BenchmarkSQL多IP連接測試RTO

原理:CM檢測主庫發生故障,不可訪問時會自動選新主,jdbc驅動通過target_session_type=master控制只連主庫,通過SQL
程序執行時間戳查看RTO

BenchmarkSQL模擬負載及重連時間

  • 時間差
16:02:13,561 [Thread-8] ERROR  jTPCCTData : Unexpected SQLException in STOCK_LEVELsage: 153MB / 897MB           
16:02:20,834 [Thread-57] FATAL  jTPCCTerminal : Unexpected SQLException on rollback: This connection has been closed.

RTO時間7.273s

3. 數據庫端觀測時間

  • 數據庫日誌

  • 時間差
2022-04-11 16:02:13.253 tid=1795056 StartAndStop ERROR: data path disc writable test failed, /opt/mogdb/data/data/db1.          
2022-04-11 16:02:20.438 tid=1815697  LOG: failover msg from cm_server, data_dir :/opt/mogdb/data/data/db1  nodetype is 2

RTO時間7.185s

總結


  • 在有負載情況(tpcc壓測產生負載,數據庫服務器CPU佔用50%左右)進行主庫宕機測試,
  • 以主庫宕機為起始點,備庫成功作為新主庫啟動成功為終止點RTO為7.185s
  • 以主庫宕機為起始點,模擬TPCC壓測的benchmarkSQL程序成功重新連接到新主庫為終止點RTO為7.273s
  • 以主庫宕機為起始點,模擬其它應用連接數據庫的go程序成功重新連接到新主庫為終止點7s
  • 由於go程序至精確到s,猜測實際時間為7.185s以上

綜上所述openGauss Cluster Manager RTO約為7s左右

作者:lihongda