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,
|
||||
SyncTicker: time.Tick(500 * time.Millisecond),
|
||||
peerRt: prt,
|
||||
reqIDGen: idutil.NewGenerator(uint8(id), time.Now()),
|
||||
reqIDGen: idutil.NewGenerator(uint16(id), time.Now()),
|
||||
forceVersionC: make(chan struct{}),
|
||||
msgSnapC: make(chan raftpb.Message, maxInFlightMsgSnap),
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ import (
|
||||
|
||||
const (
|
||||
tsLen = 5 * 8
|
||||
cntLen = 2 * 8
|
||||
cntLen = 8
|
||||
suffixLen = tsLen + cntLen
|
||||
)
|
||||
|
||||
@ -32,7 +32,7 @@ const (
|
||||
// High order byte is memberID, next 5 bytes are from timestamp,
|
||||
// and low order 2 bytes are 0s.
|
||||
// | prefix | suffix |
|
||||
// | 1 byte | 5 bytes | 2 bytes |
|
||||
// | 2 bytes | 5 bytes | 1 byte |
|
||||
// | memberID | timestamp | cnt |
|
||||
//
|
||||
// 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.
|
||||
// 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 <<
|
||||
// 65536req/ms.
|
||||
// 256req/ms(250k reqs/second).
|
||||
type Generator struct {
|
||||
mu sync.Mutex
|
||||
// high order byte
|
||||
// high order 2 bytes
|
||||
prefix uint64
|
||||
// low order 7 bytes
|
||||
// low order 6 bytes
|
||||
suffix uint64
|
||||
}
|
||||
|
||||
func NewGenerator(memberID uint8, now time.Time) *Generator {
|
||||
func NewGenerator(memberID uint16, now time.Time) *Generator {
|
||||
prefix := uint64(memberID) << suffixLen
|
||||
unixMilli := uint64(now.UnixNano()) / uint64(time.Millisecond/time.Nanosecond)
|
||||
suffix := lowbit(unixMilli, tsLen) << cntLen
|
||||
|
@ -22,7 +22,7 @@ import (
|
||||
func TestNewGenerator(t *testing.T) {
|
||||
g := NewGenerator(0x12, time.Unix(0, 0).Add(0x3456*time.Millisecond))
|
||||
id := g.Next()
|
||||
wid := uint64(0x1200000034560001)
|
||||
wid := uint64(0x12000000345601)
|
||||
if id != wid {
|
||||
t.Errorf("id = %x, want %x", id, wid)
|
||||
}
|
||||
@ -45,7 +45,7 @@ func TestNewGeneratorUnique(t *testing.T) {
|
||||
|
||||
func TestNext(t *testing.T) {
|
||||
g := NewGenerator(0x12, time.Unix(0, 0).Add(0x3456*time.Millisecond))
|
||||
wid := uint64(0x1200000034560001)
|
||||
wid := uint64(0x12000000345601)
|
||||
for i := 0; i < 1000; i++ {
|
||||
id := g.Next()
|
||||
if id != wid+uint64(i) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user