..
Gorm 分表中间件(Sharding)
Sharding 是一个高性能的 Gorm 分表中间件。它基于 Conn 层做 SQL 拦截、AST 解析、分表路由、自增主键填充,带来的额外开销极小。对开发者友好、透明,使用上与普通 SQL、Gorm 查询无差别,只需要额外注意一下分表键条件。 为您提供高性能的数据库访问
一、功能特点
- 非侵入式设计, 加载插件,指定配置,既可实现分表。
- 轻快, 非基于网络层的中间件,像 Go 一样快
- 支持多种数据库。 PostgreSQL 已通过测试,MySQL 和 SQLite 也在路上。
- 多种主键生成方式支持(Snowflake, PostgreSQL Sequence, 以及自定义支持)Snowflake 支持从主键中确定分表键。
二、示例代码
注意: 依然保持原来的方式使用 db 来查询数据库。 你只需要注意在 CURD 动作的时候,明确知道 Sharding Key 对应的分表,查询条件带 Sharding Key,以确保 Sharding 能理解数据需要对应到哪一个子表
Mysql
Gorm Sharding 中内置了 MySQL 序列主键实现,只需配置PrimaryKeyGenerator: sharding.PKMySQLSequence即可使用。
您不需要手动创建序列,当 MySQL 序列不存在时,Gorm Sharding 会检查并创建。
这个序列名后面跟着gorm_sharding_${table_name}_id_seq,例如orders表,序列名就是gorm_sharding_orders_id_seq。
/** * @Author: chentong * @Date: 2024/08/27 00:09 */ package main import ( "fmt" "testing" "gorm.io/driver/mysql" "gorm.io/gorm" "gorm.io/sharding" ) type Order struct { ID int64 `gorm:"primarykey"` UserID int64 ProductID int64 } func TestSharding_Mysql(t *testing.T) { dsn := "root:123456@tcp(localhost:3306)/dev?parseTime=True&timeout=5s" db, err := gorm.Open(mysql.Open(dsn)) if err != nil { panic(err) } for i := 0; i < 2; i += 1 { table := fmt.Sprintf("orders_%d", i) db.Exec(`DROP TABLE IF EXISTS ` + table) db.Exec("CREATE TABLE " + table + " ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `user_id` int(11) DEFAULT NULL, `product_id` int(11) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;") } db.Use(sharding.Register( sharding.Config{ ShardingKey: "user_id", // 分片key NumberOfShards: 2, // 分片数量 PrimaryKeyGenerator: sharding.PKMySQLSequence, // 主键生成器, 这里使用 mysql }, []string{"orders"}, // 需要分片 tables )) // this record will insert to orders_02 err = db.Create(&Order{UserID: 2}).Error if err != nil { fmt.Println(err) } // this record will insert to orders_03 err = db.Exec("INSERT INTO orders(user_id) VALUES(?)", int64(3)).Error if err != nil { fmt.Println(err) } // this will throw ErrMissingShardingKey error err = db.Exec("INSERT INTO orders(product_id) VALUES(1)").Error fmt.Println(err) // this will redirect query to orders_02 var orders []Order err = db.Model(&Order{}).Where("user_id", int64(2)).Find(&orders).Error if err != nil { fmt.Println(err) } fmt.Printf("%#v\n", orders) // Raw SQL also supported db.Raw("SELECT * FROM orders WHERE user_id = ?", int64(3)).Scan(&orders) fmt.Printf("%#v\n", orders) // this will throw ErrMissingShardingKey error err = db.Model(&Order{}).Where("product_id", "1").Find(&orders).Error fmt.Println(err) // Update and Delete are similar to create and query err = db.Exec("UPDATE orders SET product_id = ? WHERE user_id = ?", 2, int64(3)).Error fmt.Println(err) // nil err = db.Exec("DELETE FROM orders WHERE product_id = 3").Error fmt.Println(err) // ErrMissingShardingKey }