DBリゾルバ

DBリゾルバは、GORMに複数データベースのサポートを追加します。以下の機能がサポートされています。

  • 複数のソース、レプリカ
  • 読み取り/書き込みの分割
  • 作業中のテーブル/構造体に基づく自動接続切り替え
  • 手動接続切り替え
  • ソース/レプリカの負荷分散
  • RAW SQLで動作します
  • トランザクション

https://github.com/go-gorm/dbresolver

使用方法

import (
"gorm.io/gorm"
"gorm.io/plugin/dbresolver"
"gorm.io/driver/mysql"
)

db, err := gorm.Open(mysql.Open("db1_dsn"), &gorm.Config{})

db.Use(dbresolver.Register(dbresolver.Config{
// use `db2` as sources, `db3`, `db4` as replicas
Sources: []gorm.Dialector{mysql.Open("db2_dsn")},
Replicas: []gorm.Dialector{mysql.Open("db3_dsn"), mysql.Open("db4_dsn")},
// sources/replicas load balancing policy
Policy: dbresolver.RandomPolicy{},
// print sources/replicas mode in logger
TraceResolverMode: true,
}).Register(dbresolver.Config{
// use `db1` as sources (DB's default connection), `db5` as replicas for `User`, `Address`
Replicas: []gorm.Dialector{mysql.Open("db5_dsn")},
}, &User{}, &Address{}).Register(dbresolver.Config{
// use `db6`, `db7` as sources, `db8` as replicas for `orders`, `Product`
Sources: []gorm.Dialector{mysql.Open("db6_dsn"), mysql.Open("db7_dsn")},
Replicas: []gorm.Dialector{mysql.Open("db8_dsn")},
}, "orders", &Product{}, "secondary"))

自動接続切り替え

DBリゾルバは、作業中のテーブル/構造体に基づいて接続を自動的に切り替えます。

RAW SQLの場合、DBリゾルバはSQLからテーブル名を抽出してリゾルバと照合し、SQLが`SELECT`(`SELECT... FOR UPDATE`を除く)で始まる場合を除き、`sources`を使用します。例えば、

// `User` Resolver Examples
db.Table("users").Rows() // replicas `db5`
db.Model(&User{}).Find(&AdvancedUser{}) // replicas `db5`
db.Exec("update users set name = ?", "jinzhu") // sources `db1`
db.Raw("select name from users").Row().Scan(&name) // replicas `db5`
db.Create(&user) // sources `db1`
db.Delete(&User{}, "name = ?", "jinzhu") // sources `db1`
db.Table("users").Update("name", "jinzhu") // sources `db1`

// Global Resolver Examples
db.Find(&Pet{}) // replicas `db3`/`db4`
db.Save(&Pet{}) // sources `db2`

// Orders Resolver Examples
db.Find(&Order{}) // replicas `db8`
db.Table("orders").Find(&Report{}) // replicas `db8`

読み取り/書き込み分割

現在使用されているGORMコールバックに基づいて、DBリゾルバで読み取り/書き込みを分割します。

`Query`、`Row`コールバックの場合、`Write`モードが指定されていない限り、`replicas`を使用します。
`Raw`コールバックの場合、ステートメントは読み取り専用と見なされ、SQLが`SELECT`で始まる場合は`replicas`を使用します。

手動接続切り替え

// Use Write Mode: read user from sources `db1`
db.Clauses(dbresolver.Write).First(&user)

// Specify Resolver: read user from `secondary`'s replicas: db8
db.Clauses(dbresolver.Use("secondary")).First(&user)

// Specify Resolver and Write Mode: read user from `secondary`'s sources: db6 or db7
db.Clauses(dbresolver.Use("secondary"), dbresolver.Write).First(&user)

トランザクション

トランザクションを使用する場合、DBリゾルバはトランザクションを使い続け、設定に基づいてソース/レプリカに切り替えません。

ただし、トランザクションを開始する前に使用するDBを指定できます。例えば、

// Start transaction based on default replicas db
tx := db.Clauses(dbresolver.Read).Begin()

// Start transaction based on default sources db
tx := db.Clauses(dbresolver.Write).Begin()

// Start transaction based on `secondary`'s sources
tx := db.Clauses(dbresolver.Use("secondary"), dbresolver.Write).Begin()

負荷分散

GORMは、ポリシーに基づいてソース/レプリカの負荷分散をサポートしています。ポリシーは、以下のインターフェースを実装する構造体である必要があります。

type Policy interface {
Resolve([]gorm.ConnPool) gorm.ConnPool
}

現在、`RandomPolicy`のみが実装されており、他のポリシーが指定されていない場合はデフォルトのオプションです。

コネクションプール

db.Use(
dbresolver.Register(dbresolver.Config{ /* xxx */ }).
SetConnMaxIdleTime(time.Hour).
SetConnMaxLifetime(24 * time.Hour).
SetMaxIdleConns(100).
SetMaxOpenConns(200)
)

プラチナスポンサー

ゴールドスポンサー

プラチナスポンサー

ゴールドスポンサー