Gorm Sharding

Gorm Sharding 是一个高性能的数据库分表中间件。

它基于 Conn 层做 SQL 拦截、AST 解析、分表路由、自增主键填充,带来的额外开销极小。对开发者友好、透明,使用上与普通 SQL、Gorm 查询无差别,只需要额外注意一下分表键条件。

文档

安装
go get -u gorm.io/sharding
测试表结构
// ProjectLog 结构体
type ProjectLog struct {
    global.GVA_MODEL
    ID             int64                               `gorm:"primarykey"` // 主键ID
    ProjectId      int64                               `json:"project_id" form:"project_id" gorm:"column:project_id;comment:;"`
    UpdateContent  datatypes.JSONType[project.Project] `json:"update_content" form:"update_content" gorm:"type:json;column:update_content;comment:;"`
    UpdateContent2 datatypes.JSONType[project.Project] `json:"update_content2" form:"update_content2" gorm:"-"`
    ParentId       int64                               `json:"parent_id" form:"parent_id" gorm:"column:parent_id;comment:;"`
}

// TableName ProjectLog 表名
func (p ProjectLog) TableName() string {
    return "project_log"
}
迁移生成测试表
import (
    "fmt"
    "strconv"
    "testing"
    "gorm.io/driver/mysql"
    "gorm.io/gorm"
)
func TestMigrate(t *testing.T) {
    mysqlConfig := mysql.Config{
        DSN:                       "root:123456@tcp(127.0.0.1:3306)/admin_project?charset=utf8mb4&parseTime=True&loc=Local", // DSN data source name
        DefaultStringSize:         191,                                                                                             // string 类型字段的默认长度
        SkipInitializeWithVersion: false,                                                                                           // 根据版本自动配置

    }
    DB, err := gorm.Open(mysql.New(mysqlConfig))
    if err != nil {
        fmt.Println(err.Error())
        return
    }
    //生成128张project_log表,具体数量看自己需要了。
    for i := 0; i < 128; i++ {
        tableName := fmt.Sprintf("project_log_%0*d", 3, i) //表名
        DB.Table(tableName).AutoMigrate(&project_log.ProjectLog{})
    }
}

image
配置 Sharding 中间件,为需要分表的业务表定义他们分表的规则

import (
    "gorm.io/driver/mysql"
    "gorm.io/gorm"
    "gorm.io/sharding"
)

    mysqlConfig := mysql.Config{
        DSN:                       "root:123456@tcp(127.0.0.1:3306)/admin_project?charset=utf8mb4&parseTime=True&loc=Local", // DSN data source name
        DefaultStringSize:         191,                                                                                             // string 类型字段的默认长度
        SkipInitializeWithVersion: false,                                                                                           // 根据版本自动配置
    }
    DB, err := gorm.Open(mysql.New(mysqlConfig))
    DB.Use(sharding.Register(sharding.Config{
        ShardingKey:         "company_id",
        NumberOfShards:      128,
        PrimaryKeyGenerator: sharding.PKSnowflake,
    },   "project_log"))
    //创建数据
     DB.Create(&project_log.ProjectLog{Company_id: 1, ParentId: 1})
     DB.Create(&project_log.ProjectLog{Company_id: 1, ParentId: 2})
     DB.Create(&project_log.ProjectLog{Company_id: 1, ParentId: 3})
     DB.Create(&project_log.ProjectLog{Company_id: 1, ParentId: 4})

依然保持原来的方式使用 db 来查询数据库。 你只需要注意在 CURD 动作的时候,明确知道 Sharding Key 对应的分表,查询条件带 Sharding Key,以确保 Sharding 能理解数据需要对应到哪一个子表。

//查询数据
    var data []project.ProjectLog
     DB.Unscoped().Select("company_id,parent_id").Where("company_id =  ?", 1).
        Where("parent_id IN ?", []int{1, 2, 3, 4}).Find(&data)
    for _, v := range data {
        fmt.Printf("公司Company_id: %d,Parent_id: %d \n", v.Company_id, v.ParentId)
    }

image

go
本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 2

我想问一个问题,这个方式的分表是,逻辑分表,还是实际分表

5个月前 评论
耳东 (楼主) 4个月前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!