autoid_service: fix potential autoid decrease when leader change or close for AUTO_ID_CACHE=1 (#52602)
close pingcap/tidb#52600
This commit is contained in:
@ -107,6 +107,14 @@ func (alloc *autoIDValue) alloc4Unsigned(ctx context.Context, store kv.Storage,
|
||||
if uint64(newBase) == math.MaxUint64 {
|
||||
return 0, 0, errAutoincReadFailed
|
||||
}
|
||||
logutil.BgLogger().Info("alloc4Unsigned from",
|
||||
zap.String("category", "autoid service"),
|
||||
zap.Int64("dbID", dbID),
|
||||
zap.Int64("tblID", tblID),
|
||||
zap.Int64("from base", alloc.base),
|
||||
zap.Int64("from end", alloc.end),
|
||||
zap.Int64("to base", newBase),
|
||||
zap.Int64("to end", newEnd))
|
||||
alloc.base, alloc.end = newBase, newEnd
|
||||
}
|
||||
min = alloc.base
|
||||
@ -168,6 +176,14 @@ func (alloc *autoIDValue) alloc4Signed(ctx context.Context,
|
||||
if newBase == math.MaxInt64 {
|
||||
return 0, 0, errAutoincReadFailed
|
||||
}
|
||||
logutil.BgLogger().Info("alloc4Signed from",
|
||||
zap.String("category", "autoid service"),
|
||||
zap.Int64("dbID", dbID),
|
||||
zap.Int64("tblID", tblID),
|
||||
zap.Int64("from base", alloc.base),
|
||||
zap.Int64("from end", alloc.end),
|
||||
zap.Int64("to base", newBase),
|
||||
zap.Int64("to end", newEnd))
|
||||
alloc.base, alloc.end = newBase, newEnd
|
||||
}
|
||||
min = alloc.base
|
||||
@ -301,7 +317,19 @@ func New(selfAddr string, etcdAddr []string, store kv.Storage, tlsConfig *tls.Co
|
||||
|
||||
func newWithCli(selfAddr string, cli *clientv3.Client, store kv.Storage) *Service {
|
||||
l := owner.NewOwnerManager(context.Background(), cli, "autoid", selfAddr, autoIDLeaderPath)
|
||||
service := &Service{
|
||||
autoIDMap: make(map[autoIDKey]*autoIDValue),
|
||||
leaderShip: l,
|
||||
store: store,
|
||||
}
|
||||
l.SetBeOwnerHook(func() {
|
||||
// Reset the map to avoid a case that a node lose leadership and regain it, then
|
||||
// improperly use the stale map to serve the autoid requests.
|
||||
// See https://github.com/pingcap/tidb/issues/52600
|
||||
service.autoIDLock.Lock()
|
||||
clear(service.autoIDMap)
|
||||
service.autoIDLock.Unlock()
|
||||
|
||||
logutil.BgLogger().Info("leader change of autoid service, this node become owner",
|
||||
zap.String("addr", selfAddr),
|
||||
zap.String("category", "autoid service"))
|
||||
@ -312,11 +340,7 @@ func newWithCli(selfAddr string, cli *clientv3.Client, store kv.Storage) *Servic
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return &Service{
|
||||
autoIDMap: make(map[autoIDKey]*autoIDValue),
|
||||
leaderShip: l,
|
||||
store: store,
|
||||
}
|
||||
return service
|
||||
}
|
||||
|
||||
type mockClient struct {
|
||||
@ -353,7 +377,10 @@ func MockForTest(store kv.Storage) autoid.AutoIDAllocClient {
|
||||
// Close closes the Service and clean up resource.
|
||||
func (s *Service) Close() {
|
||||
if s.leaderShip != nil && s.leaderShip.IsOwner() {
|
||||
s.autoIDLock.Lock()
|
||||
defer s.autoIDLock.Unlock()
|
||||
for k, v := range s.autoIDMap {
|
||||
v.Lock()
|
||||
if v.base > 0 {
|
||||
err := v.forceRebase(context.Background(), s.store, k.dbID, k.tblID, v.base, v.isUnsigned)
|
||||
if err != nil {
|
||||
@ -364,6 +391,7 @@ func (s *Service) Close() {
|
||||
zap.Error(err))
|
||||
}
|
||||
}
|
||||
v.Unlock()
|
||||
}
|
||||
s.leaderShip.Cancel()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user