Skip to content

Wizard is database/sql management library for multi instance and sharding in golang

Notifications You must be signed in to change notification settings

evalphobia/wizard

Repository files navigation

Wizard

Build Status codecov.io GoDoc Join the chat at https://gitter.im/evalphobia/wizard

Wizard is database/sql management library for multi instance and sharding in golang. Inspired by MixedGauge

Supported orm list

Quick Usage

Register database clusters

import (
	_ "github.com/go-sql-driver/mysql"
	"github.com/go-xorm/xorm"

	"github.com/evalphobia/wizard"
)

type Blog struct {
	ArticleID string `xorm:"article_id pk VARCHAR(255) not null"`
	Content   string `xorm:"content text"`
}

type User struct {
	ID   int64  `xorm:"id pk BIGINT(20) not null" shard_key:"true"`
	Name string `xorm:"name VARCHAR(100) not null"`
}

func main() {
	wiz = wizard.NewWizard()

	/**
		register normal cluster
	*/

	// create engines
	blogMaster, _ = xorm.NewEngine("mysql", "root:@tcp(db-master:3306)/blog?charset=utf8")
	blogSlave01, _ = xorm.NewEngine("mysql", "root:@tcp(db-slave01:3306)/blog?charset=utf8")
	blogSlave02, _ = xorm.NewEngine("mysql", "root:@tcp(db-slave01:3306)/blog?charset=utf8")

	// create cluster with master nodel; CreateCluster(name, master-instance)
	blogCluster := wiz.CreateCluster(Blog{}, blogMaster)
	blogCluster.RegisterSlave(blogSlave01) // add slaves
	blogCluster.RegisterSlave(blogSlave02)


	/**
		register shard clusters
	*/

	// shard one
	user01Master, _ = xorm.NewEngine("mysql", "root:@/tcp(shard01-master:3306)/users?charset=utf8")
	user01Slave01, _ = xorm.NewEngine("mysql", "root:@/tcp(shard01-slave01:3306)/users?charset=utf8")
	user01Slave02, _ = xorm.NewEngine("mysql", "root:@/tcp(shard01-slave02:3306)/users?charset=utf8")

	// shard two
	user02Master, _ = xorm.NewEngine("mysql", "root:@/tcp(shard02-master:3306)/users?charset=utf8")
	user02Slave01, _ = xorm.NewEngine("mysql", "root:@/tcp(shard02-slave01:3306)/users?charset=utf8")
	user02Slave02, _ = xorm.NewEngine("mysql", "root:@/tcp(shard02-slave02:3306)/users?charset=utf8")

	// create shard clusters; CreateShardCluster(name, slot-size)
	shardClusters := wiz.CreateShardCluster(User{}, 1023)

	// create single shard set #1
	shardCluster01 := wizard.NewCluster(user01Master)
	shardCluster01.RegisterSlave(user01Slave01)
	shardCluster01.RegisterSlave(user01Slave02)

	// create single shard set #2
	shardCluster02 := wizard.NewCluster(user02Master)
	shardCluster02.RegisterSlave(user02Slave01)
	shardCluster02.RegisterSlave(user02Slave02)

	// register shards with slot; RegisterShard(min, max, cluster)
	shardClusters.RegisterShard(0, 500, shardCluster01)
	shardClusters.RegisterShard(501, 1022, shardCluster02)
}

Query on database clusters

import (
	"fmt"

	"github.com/evalphobia/wizard/orm/xorm"
)

func main() {
	orm := xorm.New(wiz)

	blog := &Blog{ArticleID: "hello-world"}
	has, err := orm.Get(blog, func(s xorm.Session) (bool, error) {
		return s.Get(blog)
	})
	// => SELECT * FROM blog WHERE article_id = "hello-world"; -- execute on blog SLAVE


	fmt.Println(has)
	fmt.Println(blog.Content)

	user := &User{
		ID:   1600, // 1600 % 1023 = 577; => shard02
		Name: "Adam Smith",
	}

	err = orm.Begin(user) // => BEGIN; -- execute on user02-MASTER
	if err != nil {
		panic("Error on transaction beginning")
	}

	total, err := orm.Insert(user, func(s xorm.Session) (int64, error) {
		return s.Insert(user)
	})
	// => INSERT INTO users VALUES(1600, "Adam Smith"); -- execute on user02-MASTER

	fmt.Println(total)

	newUser := &User{ID: 1600}
	has, err = orm.GetUsingMaster(newUser, func(s xorm.Session) (bool, error) {
		return s.Get(newUser)
	})
	// => SELECT * FROM users WHERE id = 1600; -- execute on user02-MASTER


	err = orm.Commit(user)
	// => COMMIT; -- execute on user02-MASTER
	if err != nil {
		panic("Error on transaction ending")
	}
}

Notes

  • Clusters is selected by name, which can be any value like string, struct, pointer.
    • the pointer value automatically converts to the non-pointer value.
  • Struct field tag: shard_key:"true" is used as a shard-key
    • shard_key is divided by slot size and the mod value is used for shard mapping
    • string shard_key convert to int64 with CRC64 and divided by slot-size

Other info

About

Wizard is database/sql management library for multi instance and sharding in golang

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages