golang数据库分片支持ORM和原生SQL的插件库octillery的使用
Golang数据库分片支持ORM和原生SQL的插件库Octillery的使用
Octillery是一个Go语言的数据库分片库,支持与各种ORM库(xorm、gorp、gorm、dbr等)一起使用,也支持原生SQL。它目前支持MySQL(生产环境)和SQLite3(测试环境)。
主要特性
- 支持所有实现了
database/sql
接口的ORM库 - 支持直接使用原生SQL
- 可插拔的分片算法(内置modulo和hashmap算法)
- 可插拔的数据库适配器(内置mysql和sqlite3适配器)
- 使用YAML声明式配置分片
- 可配置分片算法、数据库适配器、分片键、是否使用序列生成器等
- 支持在查询传递给数据库驱动前捕获读写查询
- 支持通过CLI进行数据库迁移(基于schemalex)
- 支持从CSV导入种子数据
安装
安装CLI工具
go get go.knocknote.io/octillery/cmd/octillery
安装库
go get go.knocknote.io/octillery
使用示例
1. 替换database/sql
导入
octillery transpose
2. 安装数据库适配器
octillery install --mysql
3. 创建YAML配置文件(databases.yml)
default: &default
adapter: mysql
encoding: utf8mb4
username: root
master:
- localhost:3306
tables:
posts:
shard: true
shard_key: user_id
shards:
- post_shard_1:
<<: *default
database: posts_shard_1
- post_shard_2:
<<: *default
database: posts_shard_2
4. 数据库迁移
octillery migrate --config databases.yml /path/to/schema
5. 在代码中使用
package main
import (
"go.knocknote.io/octillery"
"go.knocknote.io/octillery/database/sql"
)
func main() {
if err := octillery.LoadConfig("databases.yml"); err != nil {
panic(err)
}
db, _ := sql.Open("mysql", "")
db.QueryRow("...")
}
工作原理
Octillery通过以下方式工作:
- 替换
database/sql
导入为go.knocknote.io/octillery/database/sql
,从而可以捕获所有查询 - 使用vitess-sqlparser解析SQL语句
- 根据配置决定使用序列生成器还是分片键
- 根据分片算法选择目标数据库
分片策略
Octillery支持两种分片策略:
1. 使用序列生成器
当需要所有分片中的ID保持唯一时使用。工作流程:
- 应用向序列生成器请求ID值
- 序列生成器生成全局唯一ID
- 替换SQL中的ID值为生成的ID
- 根据ID值选择目标分片
2. 使用分片键(不使用序列生成器)
当不关心ID的唯一性时使用。工作流程:
- 根据分片键值选择目标分片
- 直接插入记录到选定分片
扩展支持
添加新的数据库适配器
- 实现
DBAdapter
接口 - 将新适配器文件放入
go.knocknote.io/octillery/plugin
目录
添加新的分片算法
- 实现
ShardingAlgorithm
接口 - 将新算法文件放入
go.knocknote.io/octillery/algorithm
目录
开发
安装依赖
make deps
运行测试
make test
Octillery是一个功能强大的Go语言数据库分片解决方案,可以轻松地与现有ORM或原生SQL代码集成,提供灵活的配置选项和扩展能力。
更多关于golang数据库分片支持ORM和原生SQL的插件库octillery的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang数据库分片支持ORM和原生SQL的插件库octillery的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Octillery: Golang 数据库分片插件库
Octillery 是一个支持数据库分片(sharding)的 Golang ORM 和原生 SQL 插件库,它可以在不修改现有代码的情况下为应用添加分片功能。
主要特性
- 同时支持 ORM 和原生 SQL 操作
- 支持多种分片策略
- 与现有 ORM 兼容(如 GORM)
- 支持读写分离
- 支持事务
安装
go get -u github.com/knocknote/octillery
基本使用示例
1. 配置分片
首先需要创建一个配置文件 config.yaml
:
development:
databases:
- name: user_shard_1
driver: "mysql"
datasource: "user:password@tcp(127.0.0.1:3306)/user_shard_1?parseTime=true"
show_query: true
- name: user_shard_2
driver: "mysql"
datasource: "user:password@tcp(127.0.0.1:3306)/user_shard_2?parseTime=true"
show_query: true
shards:
- name: user_shard
adapter: modulo
databases:
- user_shard_1
- user_shard_2
tables:
- users
2. 初始化 Octillery
package main
import (
"github.com/knocknote/octillery"
_ "github.com/go-sql-driver/mysql"
)
func init() {
if err := octillery.LoadConfig("config.yaml"); err != nil {
panic(err)
}
}
3. 使用 ORM 方式操作分片数据库
package main
import (
"fmt"
"log"
"github.com/knocknote/octillery"
"github.com/knocknote/octillery/connection"
)
type User struct {
ID int64 `db:"id"`
Name string `db:"name"`
Age int `db:"age"`
}
func main() {
// 获取分片连接管理器
manager := connection.NewConnectionManager()
// 通过 ORM 方式插入数据
user := &User{Name: "Alice", Age: 25}
if _, err := manager.InsertByTableName("users", user); err != nil {
log.Fatal(err)
}
// 查询数据
var users []*User
if err := manager.FindByTableName("users", &users, "name = ?", "Alice"); err != nil {
log.Fatal(err)
}
for _, u := range users {
fmt.Printf("ID: %d, Name: %s, Age: %d\n", u.ID, u.Name, u.Age)
}
}
4. 使用原生 SQL 操作分片数据库
package main
import (
"fmt"
"log"
"github.com/knocknote/octillery"
"github.com/knocknote/octillery/connection"
)
func main() {
// 获取分片连接管理器
manager := connection.NewConnectionManager()
// 原生 SQL 插入
result, err := manager.ExecByTableName("users",
"INSERT INTO users (name, age) VALUES (?, ?)", "Bob", 30)
if err != nil {
log.Fatal(err)
}
id, _ := result.LastInsertId()
fmt.Printf("Inserted user ID: %d\n", id)
// 原生 SQL 查询
rows, err := manager.QueryByTableName("users",
"SELECT id, name, age FROM users WHERE name = ?", "Bob")
if err != nil {
log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
var id int64
var name string
var age int
if err := rows.Scan(&id, &name, &age); err != nil {
log.Fatal(err)
}
fmt.Printf("ID: %d, Name: %s, Age: %d\n", id, name, age)
}
}
5. 与 GORM 集成
package main
import (
"fmt"
"log"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
"github.com/knocknote/octillery"
"github.com/knocknote/octillery/connection"
)
type User struct {
gorm.Model
Name string
Age int
}
func main() {
// 初始化 Octillery
if err := octillery.LoadConfig("config.yaml"); err != nil {
log.Fatal(err)
}
// 获取 GORM 分片连接
db, err := connection.GormConnectionManager().Connection("users")
if err != nil {
log.Fatal(err)
}
defer db.Close()
// 自动迁移
db.AutoMigrate(&User{})
// 创建记录
db.Create(&User{Name: "Charlie", Age: 35})
// 查询
var user User
db.First(&user, "name = ?", "Charlie")
fmt.Printf("User: %+v\n", user)
}
分片策略
Octillery 支持多种分片策略:
- Modulo:基于 ID 的取模分片
- Range:基于 ID 的范围分片
- Date:基于日期的分片
- Custom:自定义分片策略
可以在配置文件中指定分片策略:
shards:
- name: user_shard
adapter: modulo # 或 range, date, custom
databases:
- user_shard_1
- user_shard_2
tables:
- users
事务支持
func transferMoney(fromID, toID int64, amount float64) error {
tx, err := connection.NewConnectionManager().BeginByTableName("accounts")
if err != nil {
return err
}
defer tx.RollbackUnlessCommitted()
// 扣款
if _, err := tx.Exec("UPDATE accounts SET balance = balance - ? WHERE id = ?", amount, fromID); err != nil {
return err
}
// 存款
if _, err := tx.Exec("UPDATE accounts SET balance = balance + ? WHERE id = ?", amount, toID); err != nil {
return err
}
return tx.Commit()
}
注意事项
- 跨分片事务不被支持
- 复杂的跨分片 JOIN 操作可能会有性能问题
- 分片键的选择对性能至关重要
Octillery 为 Golang 应用提供了简单易用的数据库分片解决方案,无论是使用 ORM 还是原生 SQL,都能轻松实现分片功能。