全部学科
NodeJS全栈
nodejs
Python全栈
python
小程序首页
📅 2026-05-21 8 分钟 ✍️ juanwangdev

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

📝 发现内容有误?点击此处直接编辑

← 上一篇 预编译语句原理
下一篇 → GORM 分表策略实现
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库