Skip to content

Commit 7807365

Browse files
committed
add NextIds support
1 parent 977dad2 commit 7807365

File tree

10 files changed

+99
-9
lines changed

10 files changed

+99
-9
lines changed

CHANGELOG.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,14 @@
1-
## Version 1.2 (Pennding)
1+
## Version 1.3 (Pennding)
2+
## Version 1.2
3+
4+
New Features:
5+
- Add NextIds for get mutiple ids.
6+
- Add "start"(start timestamp) config for calculating snowflake id.
7+
8+
Bugfixes:
9+
10+
-
11+
212
## Version 1.1 (2014-12-15)
313

414
New Features:

client/client.go

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
log "code.google.com/p/log4go"
55
"encoding/json"
66
"errors"
7+
myrpc "github.com/Terry-Mao/gosnowflake/rpc"
78
"github.com/samuel/go-zookeeper/zk"
89
"math/rand"
910
"net/rpc"
@@ -20,8 +21,9 @@ const (
2021
rpcClientPingSleep = 1 * time.Second // rpc client ping need sleep
2122
rpcClientRetrySleep = 1 * time.Second // rpc client retry connect need sleep
2223

23-
RPCPing = "SnowflakeRPC.Ping"
24-
RPCNextId = "SnowflakeRPC.NextId"
24+
RPCPing = "SnowflakeRPC.Ping"
25+
RPCNextId = "SnowflakeRPC.NextId"
26+
RPCNextIds = "SnowflakeRPC.NextIds"
2527
)
2628

2729
var (
@@ -105,6 +107,18 @@ func (c *Client) Id() (id int64, err error) {
105107
return
106108
}
107109

110+
// Ids generate a snowflake id.
111+
func (c *Client) Ids(num int) (ids []int64, err error) {
112+
client, err := c.client()
113+
if err != nil {
114+
return
115+
}
116+
if err = client.Call(RPCNextIds, &myrpc.NextIdsArgs{WorkerId: c.workerId, Num: num}, &ids); err != nil {
117+
log.Error("rpc.Call(\"%s\", %d, &id) error(%v)", RPCNextId, c.workerId, err)
118+
}
119+
return
120+
}
121+
108122
// closeRpc close rpc resource.
109123
func closeRpc(clients []*rpc.Client, stop chan bool) {
110124
// rpc

client/client_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,12 @@ func Test(t *testing.T) {
5959
if err != nil {
6060
t.Error(err)
6161
}
62+
ids, err := c.Ids(5)
63+
if err != nil {
64+
t.Error(err)
65+
}
6266
fmt.Printf("gosnwoflake id: %d\n", id)
67+
fmt.Printf("gosnwoflake ids: %d\n", ids)
6368
}
6469
c.Close()
6570
// check global cache map

client/test.conf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
[base]
2222
# rpc address
23-
rpc.addr 10.33.56.165:8080
23+
rpc.addr 10.33.60.26:8080
2424

2525
# worker id
2626
worker 1

config.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,11 @@ type Config struct {
4141
PprofBind []string `goconf:"base:pprof.bind:,"`
4242
DatacenterId int64 `goconf:"snowflake:datacenter"`
4343
WorkerId []int64 `goconf:"snowflake:worker"`
44+
Start string `goconf:"snowflake:start"`
4445
ZKAddr []string `goconf:"zookeeper:addr"`
4546
ZKTimeout time.Duration `goconf:"zookeeper:timeout:time`
4647
ZKPath string `goconf:"zookeeper:path"`
48+
Twepoch int64
4749
}
4850

4951
func init() {
@@ -52,6 +54,7 @@ func init() {
5254

5355
// Init init the configuration file.
5456
func InitConfig() (err error) {
57+
var twepoch time.Time
5558
MyConf = &Config{
5659
PidFile: "/tmp/gosnowflake.pid",
5760
Dir: "/dev/null",
@@ -61,6 +64,7 @@ func InitConfig() (err error) {
6164
ThriftBind: []string{"localhost:8081"},
6265
DatacenterId: 0,
6366
WorkerId: []int64{0},
67+
Start: "2010-11-04 09:42:54",
6468
ZKAddr: []string{"localhost:2181"},
6569
ZKTimeout: time.Second * 15,
6670
ZKPath: "/gosnowflake-servers",
@@ -71,5 +75,10 @@ func InitConfig() (err error) {
7175
if err = goConf.Unmarshal(MyConf); err != nil {
7276
return
7377
}
78+
if twepoch, err = time.Parse("2006-01-02 15:04:05", MyConf.Start); err != nil {
79+
return
80+
} else {
81+
MyConf.Twepoch = twepoch.UnixNano() / int64(time.Millisecond)
82+
}
7483
return
7584
}

gosnowflake-example.conf

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,3 +125,11 @@ datacenter 0
125125
# worker 0
126126
# worker 0,1,2
127127
worker 0,1,2
128+
129+
# start set the timestamp for calculate the snowflake id, current timestamp
130+
# minus start timestamp.
131+
# default value is 2010-11-04 09:42:54
132+
# Examples:
133+
#
134+
# start 2010-11-04 09:42:54
135+
start 2010-11-04 09:42:54

id.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,13 @@ type IdWorker struct {
4343
sequence int64
4444
lastTimestamp int64
4545
workerId int64
46+
twepoch int64
4647
datacenterId int64
4748
mutex *sync.Mutex
4849
}
4950

5051
// NewIdWorker new a snowflake id generator object.
51-
func NewIdWorker(workerId, datacenterId int64) (*IdWorker, error) {
52+
func NewIdWorker(workerId, datacenterId int64, twepoch int64) (*IdWorker, error) {
5253
idWorker := &IdWorker{}
5354
if workerId > maxWorkerId || workerId < 0 {
5455
log.Error("worker Id can't be greater than %d or less than 0", maxWorkerId)
@@ -62,6 +63,7 @@ func NewIdWorker(workerId, datacenterId int64) (*IdWorker, error) {
6263
idWorker.datacenterId = datacenterId
6364
idWorker.lastTimestamp = -1
6465
idWorker.sequence = 0
66+
idWorker.twepoch = twepoch
6567
idWorker.mutex = &sync.Mutex{}
6668
log.Debug("worker starting. timestamp left shift %d, datacenter id bits %d, worker id bits %d, sequence bits %d, workerid %d", timestampLeftShift, datacenterIdBits, workerIdBits, sequenceBits, workerId)
6769
return idWorker, nil
@@ -99,5 +101,5 @@ func (id *IdWorker) NextId() (int64, error) {
99101
id.sequence = 0
100102
}
101103
id.lastTimestamp = timestamp
102-
return ((timestamp - twepoch) << timestampLeftShift) | (id.datacenterId << datacenterIdShift) | (id.workerId << workerIdShift) | id.sequence, nil
104+
return ((timestamp - id.twepoch) << timestampLeftShift) | (id.datacenterId << datacenterIdShift) | (id.workerId << workerIdShift) | id.sequence, nil
103105
}

id_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import (
2222
)
2323

2424
func TestID(t *testing.T) {
25-
id, err := NewIdWorker(0, 0)
25+
id, err := NewIdWorker(0, 0, twepoch)
2626
if err != nil {
2727
log.Error("NewIdWorker(0, 0) error(%v)", err)
2828
t.FailNow()
@@ -36,7 +36,7 @@ func TestID(t *testing.T) {
3636
}
3737

3838
func BenchmarkID(b *testing.B) {
39-
id, err := NewIdWorker(0, 0)
39+
id, err := NewIdWorker(0, 0, twepoch)
4040
if err != nil {
4141
log.Error("NewIdWorker(0, 0) error(%v)", err)
4242
b.FailNow()

rpc.go

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,16 @@ import (
2020
log "code.google.com/p/log4go"
2121
"errors"
2222
"fmt"
23+
myrpc "github.com/Terry-Mao/gosnowflake/rpc"
2324
"net"
2425
"net/rpc"
2526
"time"
2627
)
2728

29+
const (
30+
maxNextIdsNum = 100
31+
)
32+
2833
type SnowflakeRPC struct {
2934
idWorkers []*IdWorker
3035
}
@@ -41,7 +46,7 @@ func InitRPC() error {
4146
log.Error("init workerId: %d already exists", workerId)
4247
return fmt.Errorf("init workerId: %d exists", workerId)
4348
}
44-
idWorker, err := NewIdWorker(workerId, MyConf.DatacenterId)
49+
idWorker, err := NewIdWorker(workerId, MyConf.DatacenterId, MyConf.Twepoch)
4550
if err != nil {
4651
log.Error("NewIdWorker(%d, %d) error(%v)", MyConf.DatacenterId, workerId)
4752
return err
@@ -98,6 +103,37 @@ func (s *SnowflakeRPC) NextId(workerId int64, id *int64) error {
98103
return nil
99104
}
100105

106+
// NextIds generate specified num ids.
107+
func (s *SnowflakeRPC) NextIds(args *myrpc.NextIdsArgs, ids *[]int64) error {
108+
if args == nil {
109+
return errors.New("args is nil")
110+
}
111+
if args.WorkerId > maxWorkerId || args.WorkerId < 0 {
112+
log.Error("worker Id can't be greater than %d or less than 0", maxWorkerId)
113+
return errors.New(fmt.Sprintf("worker Id: %d error", args.WorkerId))
114+
}
115+
if args.Num > maxNextIdsNum || args.Num < 0 {
116+
log.Error("num can't be greater than %d or less than 0", maxNextIdsNum)
117+
return errors.New(fmt.Sprintf("num: %d error", args.Num))
118+
}
119+
if worker := s.idWorkers[args.WorkerId]; worker == nil {
120+
log.Warn("workerId: %d not register", args.WorkerId)
121+
return fmt.Errorf("snowflake workerId: %d don't register in this service", args.WorkerId)
122+
} else {
123+
tids := make([]int64, args.Num)
124+
for i := 0; i < args.Num; i++ {
125+
if tid, err := worker.NextId(); err != nil {
126+
log.Error("worker.NextId() error(%v)", err)
127+
return err
128+
} else {
129+
tids[i] = tid
130+
}
131+
}
132+
*ids = tids
133+
}
134+
return nil
135+
}
136+
101137
// DatacenterId return the services's datacenterId.
102138
func (s *SnowflakeRPC) DatacenterId(ignore int, dataCenterId *int64) error {
103139
*dataCenterId = MyConf.DatacenterId

rpc/args.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package rpc
2+
3+
type NextIdsArgs struct {
4+
WorkerId int64 // snowflake worker id
5+
Num int // batch next id number
6+
}

0 commit comments

Comments
 (0)