GORM 分库路由配置
GORM 通过自定义 Dialector 和连接池 Resolver 实现多数据源动态路由,支撑读写分离、分库部署等场景。
多数据源基础配置
初始化多个数据库连接
Go
var (
dbMaster *gorm.DB
dbSlave1 *gorm.DB
dbSlave2 *gorm.DB
)
func InitDBs() error {
var err error
// 主库(写)
dbMaster, err = gorm.Open(mysql.Open("master_dsn"), &gorm.Config{})
if err != nil {
return err
}
// 从库1(读)
dbSlave1, err = gorm.Open(mysql.Open("slave1_dsn"), &gorm.Config{})
if err != nil {
return err
}
// 从库2(读)
dbSlave2, err = gorm.Open(mysql.Open("slave2_dsn"), &gorm.Config{})
return err
}
读写分离插件
使用 dbresolver 插件
Go
import (
"gorm.io/plugin/dbresolver"
"gorm.io/driver/mysql"
)
func SetupDBResolver() (*gorm.DB, error) {
db, err := gorm.Open(mysql.Open("master_dsn"), &gorm.Config{})
if err != nil {
return nil, err
}
// 配置读写分离
err = db.Use(dbresolver.Register(dbresolver.Config{
// 写库(主库)
Sources: []gorm.Dialector{mysql.Open("master_dsn")},
// 读库(从库)
Replicas: []gorm.Dialector{
mysql.Open("slave1_dsn"),
mysql.Open("slave2_dsn"),
},
// 指定按模型路由
Policy: dbresolver.RandomPolicy{},
}))
return db, err
}
注意:
dbresolver插件会自动将写操作路由到Sources,读操作路由到Replicas。
按业务规则路由
多数据库分片路由
Go
func SetupShardResolver() (*gorm.DB, error) {
db, err := gorm.Open(mysql.Open("default_dsn"), &gorm.Config{})
if err != nil {
return nil, err
}
// 配置多数据源路由
err = db.Use(dbresolver.Register(dbresolver.Config{
Sources: []gorm.Dialector{mysql.Open("db0_dsn")},
Replicas: []gorm.Dialector{mysql.Open("db0_ro_dsn")},
}).Register(dbresolver.Config{
Sources: []gorm.Dialector{mysql.Open("db1_dsn")},
Replicas: []gorm.Dialector{mysql.Open("db1_ro_dsn")},
}, "Order")) // 按模型名路由
return db, err
}
自定义路由策略
Go
type CustomResolverPolicy struct{}
func (p CustomResolverPolicy) Resolve(dbs []gorm.ConnPool) gorm.ConnPool {
// 根据业务上下文选择数据源
tenantID := GetTenantFromContext()
idx := tenantID % len(dbs)
return dbs[idx]
}
// 注册自定义策略
db.Use(dbresolver.Register(dbresolver.Config{
Sources: []gorm.Dialector{
mysql.Open("db0_dsn"),
mysql.Open("db1_dsn"),
mysql.Open("db2_dsn"),
},
Policy: CustomResolverPolicy{},
}))
上下文动态切换
强制指定读写库
Go
// 强制使用写库
db.Clauses(dbresolver.Write).Create(&order)
// 强制使用读库
db.Clauses(dbresolver.Read).Find(&orders)
// 切换指定数据库
db.Clauses(dbresolver.Use("db1")).Find(&orders)
连接池调优
配置连接池参数
Go
func ConfigurePool(db *gorm.DB) error {
sqlDB, err := db.DB()
if err != nil {
return err
}
// 设置最大空闲连接数
sqlDB.SetMaxIdleConns(10)
// 设置最大打开连接数
sqlDB.SetMaxOpenConns(100)
// 设置连接最大存活时间
sqlDB.SetConnMaxLifetime(time.Hour)
return nil
}
注意: 多数据源场景需为每个连接池单独调优,避免连接数耗尽或闲置浪费。
要点总结
- 使用
dbresolver插件实现读写分离和多数据源管理 Sources处理写操作,Replicas处理读操作- 可按模型、表或自定义策略路由到目标数据库
- 通过
Clauses(dbresolver.Write/Read)强制切换数据源 - 每个数据源连接池需独立调优,确保连接数合理分配
存放路径:D:\git2\jwdev\articles\GORM\专家\分库分表与多租户\分库路由配置.md
📝 发现内容有误?点击此处直接编辑