mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
pkg/idutil: reduce conflict rate from 1% to 0.005%
Perviously, we only use 8bits from member identification in id generation. The conflict rate is A(256,3)/256^3, which is around 1%. Now we use 16bites to reduce the rate to 0.005%. We can attach the full member id into id generation if needed...
This commit is contained in:
parent
0cdf1c45cf
commit
e44e753e66
@ -358,7 +358,7 @@ func NewServer(cfg *ServerConfig) (*EtcdServer, error) {
|
|||||||
lstats: lstats,
|
lstats: lstats,
|
||||||
SyncTicker: time.Tick(500 * time.Millisecond),
|
SyncTicker: time.Tick(500 * time.Millisecond),
|
||||||
peerRt: prt,
|
peerRt: prt,
|
||||||
reqIDGen: idutil.NewGenerator(uint8(id), time.Now()),
|
reqIDGen: idutil.NewGenerator(uint16(id), time.Now()),
|
||||||
forceVersionC: make(chan struct{}),
|
forceVersionC: make(chan struct{}),
|
||||||
msgSnapC: make(chan raftpb.Message, maxInFlightMsgSnap),
|
msgSnapC: make(chan raftpb.Message, maxInFlightMsgSnap),
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
tsLen = 5 * 8
|
tsLen = 5 * 8
|
||||||
cntLen = 2 * 8
|
cntLen = 8
|
||||||
suffixLen = tsLen + cntLen
|
suffixLen = tsLen + cntLen
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -32,7 +32,7 @@ const (
|
|||||||
// High order byte is memberID, next 5 bytes are from timestamp,
|
// High order byte is memberID, next 5 bytes are from timestamp,
|
||||||
// and low order 2 bytes are 0s.
|
// and low order 2 bytes are 0s.
|
||||||
// | prefix | suffix |
|
// | prefix | suffix |
|
||||||
// | 1 byte | 5 bytes | 2 bytes |
|
// | 2 bytes | 5 bytes | 1 byte |
|
||||||
// | memberID | timestamp | cnt |
|
// | memberID | timestamp | cnt |
|
||||||
//
|
//
|
||||||
// The timestamp 5 bytes is different when the machine is restart
|
// The timestamp 5 bytes is different when the machine is restart
|
||||||
@ -42,16 +42,16 @@ const (
|
|||||||
// The count field may overflow to timestamp field, which is intentional.
|
// The count field may overflow to timestamp field, which is intentional.
|
||||||
// It helps to extend the event window to 2^56. This doesn't break that
|
// It helps to extend the event window to 2^56. This doesn't break that
|
||||||
// id generated after restart is unique because etcd throughput is <<
|
// id generated after restart is unique because etcd throughput is <<
|
||||||
// 65536req/ms.
|
// 256req/ms(250k reqs/second).
|
||||||
type Generator struct {
|
type Generator struct {
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
// high order byte
|
// high order 2 bytes
|
||||||
prefix uint64
|
prefix uint64
|
||||||
// low order 7 bytes
|
// low order 6 bytes
|
||||||
suffix uint64
|
suffix uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewGenerator(memberID uint8, now time.Time) *Generator {
|
func NewGenerator(memberID uint16, now time.Time) *Generator {
|
||||||
prefix := uint64(memberID) << suffixLen
|
prefix := uint64(memberID) << suffixLen
|
||||||
unixMilli := uint64(now.UnixNano()) / uint64(time.Millisecond/time.Nanosecond)
|
unixMilli := uint64(now.UnixNano()) / uint64(time.Millisecond/time.Nanosecond)
|
||||||
suffix := lowbit(unixMilli, tsLen) << cntLen
|
suffix := lowbit(unixMilli, tsLen) << cntLen
|
||||||
|
@ -22,7 +22,7 @@ import (
|
|||||||
func TestNewGenerator(t *testing.T) {
|
func TestNewGenerator(t *testing.T) {
|
||||||
g := NewGenerator(0x12, time.Unix(0, 0).Add(0x3456*time.Millisecond))
|
g := NewGenerator(0x12, time.Unix(0, 0).Add(0x3456*time.Millisecond))
|
||||||
id := g.Next()
|
id := g.Next()
|
||||||
wid := uint64(0x1200000034560001)
|
wid := uint64(0x12000000345601)
|
||||||
if id != wid {
|
if id != wid {
|
||||||
t.Errorf("id = %x, want %x", id, wid)
|
t.Errorf("id = %x, want %x", id, wid)
|
||||||
}
|
}
|
||||||
@ -45,7 +45,7 @@ func TestNewGeneratorUnique(t *testing.T) {
|
|||||||
|
|
||||||
func TestNext(t *testing.T) {
|
func TestNext(t *testing.T) {
|
||||||
g := NewGenerator(0x12, time.Unix(0, 0).Add(0x3456*time.Millisecond))
|
g := NewGenerator(0x12, time.Unix(0, 0).Add(0x3456*time.Millisecond))
|
||||||
wid := uint64(0x1200000034560001)
|
wid := uint64(0x12000000345601)
|
||||||
for i := 0; i < 1000; i++ {
|
for i := 0; i < 1000; i++ {
|
||||||
id := g.Next()
|
id := g.Next()
|
||||||
if id != wid+uint64(i) {
|
if id != wid+uint64(i) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user