Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat:support same database has multiple tables with different sharding key #170

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 21 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,19 @@ import (

db, err := gorm.Open(postgres.New(postgres.Config{DSN: "postgres://localhost:5432/sharding-db?sslmode=disable"))

db.Use(sharding.Register(sharding.Config{
db.Use(sharding.Register(map[any]sharding.Config{"orders": {
ShardingKey: "user_id",
NumberOfShards: 64,
PrimaryKeyGenerator: sharding.PKSnowflake,
}, "orders", Notification{}, AuditLog{}))
}, Notification{}: {
ShardingKey: "user_id",
NumberOfShards: 64,
PrimaryKeyGenerator: sharding.PKSnowflake,
}, AuditLog{}: {
ShardingKey: "user_id",
NumberOfShards: 64,
PrimaryKeyGenerator: sharding.PKSnowflake,
}}))
// This case for show up give notifications, audit_logs table use same sharding rule.
```

Expand Down Expand Up @@ -97,11 +105,11 @@ Recommend options:
Built-in Snowflake primary key generator.

```go
db.Use(sharding.Register(sharding.Config{
db.Use(sharding.Register(map[any]sharding.Config{"orders": {
ShardingKey: "user_id",
NumberOfShards: 64,
PrimaryKeyGenerator: sharding.PKSnowflake,
}, "orders")
}}))
```

### Use PostgreSQL Sequence
Expand All @@ -113,11 +121,11 @@ You don't need create sequence manually, Gorm Sharding check and create when the
This sequence name followed `gorm_sharding_${table_name}_id_seq`, for example `orders` table, the sequence name is `gorm_sharding_orders_id_seq`.

```go
db.Use(sharding.Register(sharding.Config{
db.Use(sharding.Register(map[any]sharding.Config{"orders": {
ShardingKey: "user_id",
NumberOfShards: 64,
PrimaryKeyGenerator: sharding.PKPGSequence,
}, "orders")
}}))
```

### Use MySQL Sequence
Expand All @@ -129,11 +137,11 @@ You don't need create sequence manually, Gorm Sharding check and create when the
This sequence name followed `gorm_sharding_${table_name}_id_seq`, for example `orders` table, the sequence name is `gorm_sharding_orders_id_seq`.

```go
db.Use(sharding.Register(sharding.Config{
db.Use(sharding.Register(map[any]sharding.Config{"orders": {
ShardingKey: "user_id",
NumberOfShards: 64,
PrimaryKeyGenerator: sharding.PKMySQLSequence,
}, "orders")
}}))
```

### No primary key
Expand All @@ -158,11 +166,11 @@ db.Use(dbresolver.Register(dbresolver.Config{
Replicas: []gorm.Dialector{dbRead.Dialector},
}))

db.Use(sharding.Register(sharding.Config{
ShardingKey: "user_id",
NumberOfShards: 64,
PrimaryKeyGenerator: sharding.PKSnowflake,
}))
db.Use(sharding.Register(map[any]sharding.Config{"orders": {
ShardingKey: "user_id",
NumberOfShards: 64,
PrimaryKeyGenerator: sharding.PKSnowflake,
}})))
```

## Sharding process
Expand Down
4 changes: 2 additions & 2 deletions examples/order.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@ func main() {
)`)
}

middleware := sharding.Register(sharding.Config{
middleware := sharding.Register(map[any]sharding.Config{"orders": {
ShardingKey: "user_id",
NumberOfShards: 64,
PrimaryKeyGenerator: sharding.PKSnowflake,
}, "orders")
}})
db.Use(middleware)

// this record will insert to orders_02
Expand Down
14 changes: 6 additions & 8 deletions sharding.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ type Sharding struct {
querys sync.Map
snowflakeNodes []*snowflake.Node

_config Config
_tables []any
_configs map[any]Config

mutex sync.RWMutex
}
Expand Down Expand Up @@ -103,24 +102,23 @@ type Config struct {
PrimaryKeyGeneratorFn func(tableIdx int64) int64
}

func Register(config Config, tables ...any) *Sharding {
func Register(configs map[any]Config) *Sharding {
return &Sharding{
_config: config,
_tables: tables,
_configs: configs,
}
}

func (s *Sharding) compile() error {
if s.configs == nil {
s.configs = make(map[string]Config)
}
for _, table := range s._tables {
for table, config := range s._configs {
if t, ok := table.(string); ok {
s.configs[t] = s._config
s.configs[t] = config
} else {
stmt := &gorm.Statement{DB: s.DB}
if err := stmt.Parse(table); err == nil {
s.configs[stmt.Table] = s._config
s.configs[stmt.Table] = config
} else {
return err
}
Expand Down
10 changes: 5 additions & 5 deletions sharding_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,8 @@ func init() {
},
}

middleware = Register(shardingConfig, &Order{})
middlewareNoID = Register(shardingConfigNoID, &Order{})
middleware = Register(map[any]Config{&Order{}: shardingConfig})
middlewareNoID = Register(map[any]Config{&Order{}: shardingConfigNoID})

fmt.Println("Clean only tables ...")
dropTables()
Expand Down Expand Up @@ -391,7 +391,7 @@ func TestPKSnowflake(t *testing.T) {
})
}
shardingConfig.PrimaryKeyGenerator = PKSnowflake
middleware := Register(shardingConfig, &Order{})
middleware := Register(map[any]Config{&Order{}: shardingConfig})
db.Use(middleware)

node, _ := snowflake.NewNode(0)
Expand All @@ -412,7 +412,7 @@ func TestPKPGSequence(t *testing.T) {
DisableForeignKeyConstraintWhenMigrating: true,
})
shardingConfig.PrimaryKeyGenerator = PKPGSequence
middleware := Register(shardingConfig, &Order{})
middleware := Register(map[any]Config{&Order{}: shardingConfig})
db.Use(middleware)

db.Exec("SELECT setval('" + pgSeqName("orders") + "', 42)")
Expand All @@ -430,7 +430,7 @@ func TestPKMySQLSequence(t *testing.T) {
DisableForeignKeyConstraintWhenMigrating: true,
})
shardingConfig.PrimaryKeyGenerator = PKMySQLSequence
middleware := Register(shardingConfig, &Order{})
middleware := Register(map[any]Config{&Order{}: shardingConfig})
db.Use(middleware)

db.Exec("UPDATE `" + mySQLSeqName("orders") + "` SET id = 42")
Expand Down
Loading