Skip to content

Commit

Permalink
init commit
Browse files Browse the repository at this point in the history
  • Loading branch information
hyperphoton committed Jan 14, 2022
0 parents commit d9471b4
Show file tree
Hide file tree
Showing 8 changed files with 1,189 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.DS_Store
30 changes: 30 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
module github.com/longbridgeapp/gorm-sharding

go 1.17

require (
github.com/longbridgeapp/assert v0.1.0
github.com/longbridgeapp/sqlparser v0.2.0
github.com/stretchr/testify v1.7.0
gorm.io/driver/postgres v1.1.0
gorm.io/gorm v1.21.16
gorm.io/hints v0.0.0-20210614014355-b8cf5492cb94
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530 // indirect
github.com/jackc/pgio v1.0.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgproto3/v2 v2.1.1 // indirect
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect
github.com/jackc/pgtype v1.8.1 // indirect
github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirect
golang.org/x/text v0.3.6 // indirect
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
)
515 changes: 515 additions & 0 deletions go.sum

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions keygen/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# keygen

Distributed Primary Key generator.
3 changes: 3 additions & 0 deletions keygen/README_zh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# keygen

分布式主键生成器。
101 changes: 101 additions & 0 deletions keygen/id.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package keygen

import (
"errors"
"log"
"net"
"sync"
"time"
)

// | 1bit unused | 41bits timestamp | 6bits worker |9bits table | 7bits sequence |
const (
timeLeft = uint8(22)
workerLeft = uint8(16)
tableLeft = uint8(7)
twepoch = int64(1624204800000) // start from 2021-06-21
seqMax = 127
)

type Sequence struct {
number int64
timestamp int64
sync.Mutex
}

func (s *Sequence) next(timestamp int64) int64 {
s.Lock()
defer s.Unlock()

if timestamp > s.timestamp {
s.timestamp = timestamp
s.number = 1
} else {
s.number = s.number + 1
}

return s.number
}

var sequence Sequence
var worker int64

func init() {
ipv4, err := getIPv4()
if err != nil {
log.Fatal(err)
}
worker = int64(ipv4[3]) % 64
sequence = Sequence{}
}

// Next generate a distributed Primary Key
// tableIdx - table sharding index
func Next(tableIdx int64) int64 {
var now int64
var seq int64

for i := 0; i <= 10; i++ {
now = time.Now().UnixNano() / 1e6
seq = sequence.next(now)
if seq <= seqMax {
break
}
time.Sleep(time.Microsecond * 100)
}

return int64(((now - twepoch) << timeLeft) |
(worker << workerLeft) |
(tableIdx << tableLeft) |
seq)
}

// getWorkerNumber get the worker number from id
func getWorkerNumber(id int64) int {
return int(id >> int64(workerLeft) & 63)
}

// TableIdx get the table index from id
// Give a ID return idx of table shard
func TableIdx(id int64) int {
return int(id >> int64(tableLeft) & 511)
}

// getIPv4 get the IPv4 address
func getIPv4() (ip net.IP, err error) {
addrs, err := net.InterfaceAddrs()
if err != nil {
return
}

for _, a := range addrs {
if ipnet, ok := a.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
ipv4 := ipnet.IP.To4()
if ipv4 != nil {
return ipv4, nil
}
}
}

return nil, errors.New("can not get ipv4")
}
Loading

0 comments on commit d9471b4

Please sign in to comment.