GORM 读写分离实现
读写分离是数据库扩展的常见方案,本文介绍 GORM 中配置主从分离与自动路由的核心方法。
什么是读写分离
读写分离指将写入操作路由到主库,读取操作路由到从库,实现负载分散与性能提升。
基础配置
使用 dbresolver 插件配置读写分离。
Go
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/plugin/dbresolver"
)
db, err := gorm.Open(mysql.Open("master_dsn"), &gorm.Config{})
db.Use(dbresolver.Register(dbresolver.Config{
// 主库:写入
Sources: []gorm.Dialector{mysql.Open("master_dsn")},
// 从库:读取
Replicas: []gorm.Dialector{
mysql.Open("replica1_dsn"),
mysql.Open("replica2_dsn"),
},
// 负载均衡策略:随机
Policy: dbresolver.RandomPolicy{},
}))
自动路由规则
GORM 根据操作类型自动路由:
| 操作类型 | 路由目标 | 示例 |
|---|---|---|
| 写入 | 主库 | Create, Update, Delete |
| 读取 | 从库 | Find, First, Select |
| 事务 | 主库 | Begin().Create().Commit() |
Go
// 自动路由到从库
var users []User
db.Find(&users)
// 自动路由到主库
db.Create(&User{Name: "test"})
// 事务固定使用主库
tx := db.Begin()
tx.Create(&order)
tx.Model(&user).Update("balance", -100)
tx.Commit()
指定数据源
可强制指定使用主库或从库。
Go
// 强制从主库读取(强一致性场景)
db.Clauses(dbresolver.Write).Find(&users)
// 强制从从库读取
db.Clauses(dbresolver.Read).First(&user)
多数据库组
不同模型可绑定不同数据库组。
Go
db.Use(dbresolver.Register(dbresolver.Config{
Sources: []gorm.Dialector{mysql.Open("orders_master")},
Replicas: []gorm.Dialector{mysql.Open("orders_replica")},
}).For("Order", "Payment"))
db.Use(dbresolver.Register(dbresolver.Config{
Sources: []gorm.Dialector{mysql.Open("users_master")},
Replicas: []gorm.Dialector{mysql.Open("users_replica")},
}).For("User", "Profile"))
- **主从延迟:**从库可能存在复制延迟,强一致性查询应使用主库。
- **事务固定主库:**事务内所有操作路由到主库,避免主从不一致。
- **健康检查:**定期检测从库状态,自动剔除不可用节点。
- **负载均衡:**默认轮询策略,可自定义路由逻辑。
要点总结
- 使用 dbresolver 插件配置读写分离,简洁高效。
- GORM 自动路由:写入走主库,读取走从库。
- 强一致性场景强制使用主库:
db.Clauses(dbresolver.Write)。 - 不同模型可绑定不同数据库组,实现细粒度控制。
存放路径: D:\git2\jwdev\articles\GORM\专家\性能优化与调优\读写分离实现.md
📝 发现内容有误?点击此处直接编辑