golang主从数据库自动负载均衡代理插件库mssqlx的使用
golang主从数据库自动负载均衡代理插件库mssqlx的使用
简介
mssqlx是一个可嵌入、高可用、高性能且轻量级的数据库客户端库,支持Go 1.9及以上版本。主要特性包括:
- 作为sqlx的扩展层
- 自动代理任何主从、主主数据库,兼容Wsrep、Galera集群等
- 自动轻量级轮询负载均衡查询
- 内置对Wsrep、Galera和一些数据库驱动程序的错误处理
- 自动健康检查
安装
go get -u github.com/linxGnu/mssqlx
连接数据库
mssqlx兼容所有database/sql
支持的数据库类型。以下是MySQL使用示例:
import (
_ "github.com/go-sql-driver/mysql"
"github.com/linxGnu/mssqlx"
)
dsn := "root:123@(%s:3306)/test?charset=utf8&collation=utf8_general_ci&parseTime=true"
masterDSNs := []string{
fmt.Sprintf(dsn, "172.31.25.233"), // 主节点1地址
fmt.Sprintf(dsn, "172.31.24.233"), // 主节点2地址(如果有)
fmt.Sprintf(dsn, "172.31.23.233"), // 主节点3地址(如果有)
}
slaveDSNs := []string{
fmt.Sprintf(dsn, "172.31.25.234"), // 从节点1地址
fmt.Sprintf(dsn, "172.31.25.235"), // 从节点2地址
fmt.Sprintf(dsn, "172.31.25.236"), // 从节点3地址
}
db, _ := mssqlx.ConnectMasterSlaves("mysql", masterDSNs, slaveDSNs)
连接Galera集群
建议设置如下标志:
db, _ := mssqlx.ConnectMasterSlaves("mysql", masterDSNs, slaveDSNs, mssqlx.WithWsrep())
自定义读查询源
读查询将在主节点和从节点之间分配:
db, _ := mssqlx.ConnectMasterSlaves("mysql", masterDSNs, slaveDSNs, mssqlx.WithReadQuerySource(mssqlx.ReadQuerySourceAll))
配置
建议在查询前进行配置:
db.SetMaxIdleConns(20) // 设置所有节点的最大空闲连接数
// db.SetMasterMaxIdleConns(20) // 设置主节点的最大空闲连接数
// db.SetSlaveMaxIdleConns(20) // 设置从节点的最大空闲连接数
db.SetMaxOpenConns(50) // 设置所有节点的最大打开连接数
// db.SetMasterMaxOpenConns(50)
// db.SetSlaveMaxOpenConns(50)
// 如果节点失败,定期检查健康状态以自动重连(毫秒),默认为500
db.SetHealthCheckPeriod(1000)
// db.SetMasterHealthCheckPeriod(1000)
// db.SetSlaveHealthCheckPeriod(1000)
查询示例
Select查询
type Person struct {
FirstName string `db:"first_name"`
LastName string `db:"last_name"`
Email string
Data []byte
}
var people []Person
db.Select(&people, "SELECT * FROM person WHERE id > ? and id < ? ORDER BY first_name ASC", 1, 1000)
Get查询
var person Person
db.Get(&person, "SELECT * FROM person WHERE id = ?", 1)
Queryx查询
// 使用单个结构体循环遍历行
var person Person
rows, err := db.Queryx("SELECT * FROM person") // 或者使用db.QueryxOnMaster(...)
for rows.Next() {
if err := rows.StructScan(&person); err != nil {
log.Fatalln(err)
}
fmt.Printf("%#v\n", person)
}
命名查询
// 使用单个结构体循环遍历行
var person Person
rows, err := db.NamedQuery(`SELECT * FROM person WHERE first_name = :fn`, map[string]interface{}{"fn": "Bin"}) // 或者使用db.NamedQueryOnMaster(...)
for rows.Next() {
if err := rows.StructScan(&person); err != nil {
log.Fatalln(err)
}
fmt.Printf("%#v\n", person)
}
Exec操作(插入/更新/删除等)
result, err := db.Exec("DELETE FROM person WHERE id < ?", 100)
事务
// 推荐这样写事务
tx, e := db.Begin()
if e != nil {
return e
}
shouldAutoRollBack := true
defer func() {
if e := recover(); e != nil {
err = fmt.Errorf("%v", e)
tx.Rollback()
} else if err != nil && shouldAutoRollBack {
tx.Rollback()
}
}()
if _, err = tx.Exec("INSERT INTO person(first_name, last_name, email, data) VALUES (?,?,?,?)", "Jon", "Dow", "jon@gmail", []byte{1, 2}); err != nil {
return
}
if _, err = tx.Exec("INSERT INTO person(first_name, last_name, email, data) VALUES (?,?,?,?)", "Jon", "Snow", "snow@gmail", []byte{1}); err != nil {
return
}
if err = tx.Commit(); err != nil {
shouldAutoRollBack = false
}
注意事项
- API支持仅在主节点或从节点上执行查询。在主节点上查询的函数名有后缀
OnMaster
,在从节点上查询的函数名有后缀OnSlave
- 默认情况下,
select/show
查询会在从节点上负载均衡
更多关于golang主从数据库自动负载均衡代理插件库mssqlx的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang主从数据库自动负载均衡代理插件库mssqlx的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
MSSQLX: Golang主从数据库自动负载均衡代理插件库
MSSQLX是一个用于Golang的数据库代理库,专门为Microsoft SQL Server设计,提供主从数据库的自动负载均衡功能。下面我将详细介绍它的使用方法和示例代码。
主要特性
- 自动识别主从数据库
- 读写分离
- 负载均衡
- 连接池管理
- 故障自动转移
安装
go get github.com/denisenkom/go-mssqldb
go get github.com/your-repo/mssqlx
基本使用示例
package main
import (
"database/sql"
"fmt"
"log"
"time"
"github.com/denisenkom/go-mssqldb"
"github.com/your-repo/mssqlx"
)
func main() {
// 配置主从服务器
config := mssqlx.Config{
Master: mssqlx.ServerConfig{
Host: "master-server",
Port: 1433,
User: "sa",
Password: "your-password",
Database: "your-db",
},
Slaves: []mssqlx.ServerConfig{
{
Host: "slave1-server",
Port: 1433,
User: "sa",
Password: "your-password",
Database: "your-db",
},
{
Host: "slave2-server",
Port: 1433,
User: "sa",
Password: "your-password",
Database: "your-db",
},
},
MaxOpenConns: 100,
MaxIdleConns: 10,
ConnMaxLifetime: time.Hour,
}
// 创建代理
proxy, err := mssqlx.NewProxy(config)
if err != nil {
log.Fatal("Failed to create proxy:", err)
}
defer proxy.Close()
// 执行查询(自动路由到从库)
rows, err := proxy.Query("SELECT * FROM users WHERE status = ?", 1)
if err != nil {
log.Fatal("Query failed:", err)
}
defer rows.Close()
// 处理结果...
for rows.Next() {
var id int
var name string
if err := rows.Scan(&id, &name); err != nil {
log.Fatal("Scan failed:", err)
}
fmt.Printf("ID: %d, Name: %s\n", id, name)
}
// 执行写入(自动路由到主库)
result, err := proxy.Exec("UPDATE users SET status = ? WHERE id = ?", 2, 123)
if err != nil {
log.Fatal("Exec failed:", err)
}
affected, _ := result.RowsAffected()
fmt.Printf("Rows affected: %d\n", affected)
}
高级功能
1. 自定义负载均衡策略
// 自定义负载均衡策略
type CustomBalancer struct{}
func (b *CustomBalancer) Select(slaves []*sql.DB) *sql.DB {
// 实现自定义的选择逻辑,例如轮询、随机或基于权重的选择
return slaves[0] // 简单示例:总是选择第一个从库
}
// 使用自定义负载均衡器
config := mssqlx.Config{
// ...其他配置
Balancer: &CustomBalancer{},
}
2. 事务处理
// 开始事务(总是在主库上执行)
tx, err := proxy.Begin()
if err != nil {
log.Fatal("Begin transaction failed:", err)
}
// 执行事务操作
_, err = tx.Exec("UPDATE accounts SET balance = balance - ? WHERE id = ?", 100, 1)
if err != nil {
tx.Rollback()
log.Fatal("Update failed:", err)
}
_, err = tx.Exec("UPDATE accounts SET balance = balance + ? WHERE id = ?", 100, 2)
if err != nil {
tx.Rollback()
log.Fatal("Update failed:", err)
}
// 提交事务
err = tx.Commit()
if err != nil {
log.Fatal("Commit failed:", err)
}
3. 手动指定数据库
// 强制使用主库查询
rows, err := proxy.Master().Query("SELECT * FROM sensitive_data")
// 强制使用特定从库查询
rows, err := proxy.Slave(1).Query("SELECT * FROM large_table")
4. 健康检查与监控
// 获取主库状态
masterStatus := proxy.MasterStatus()
fmt.Printf("Master status: %+v\n", masterStatus)
// 获取所有从库状态
for i, slaveStatus := range proxy.SlavesStatus() {
fmt.Printf("Slave %d status: %+v\n", i, slaveStatus)
}
// 设置健康检查间隔
proxy.SetHealthCheckInterval(30 * time.Second)
最佳实践
- 连接池配置:根据应用负载合理设置MaxOpenConns和MaxIdleConns
- 错误处理:实现重试逻辑处理临时性故障
- 监控:定期检查数据库节点健康状况
- 读写分离:确保只读查询确实不需要最新数据时才路由到从库
注意事项
- 主从复制延迟可能导致从库数据不是最新的
- 事务中的所有操作都会在主库上执行
- 某些特定SQL可能需要在主库上执行(如存储过程调用)
MSSQLX通过简单的API抽象了主从数据库的复杂性,使得开发者可以专注于业务逻辑而不必担心数据库路由的细节。