From 03593f1061970f9b5b00b9a3ac4f0d0f92b10a89 Mon Sep 17 00:00:00 2001 From: Lutty Date: Sun, 7 Aug 2022 22:48:09 +0800 Subject: [PATCH 1/2] fix bug --- core/blockchain_impl.go | 8 +++++- internal/tikv/redis_helper/lock.go | 45 ++++++++++++++++++++++++------ 2 files changed, 43 insertions(+), 10 deletions(-) diff --git a/core/blockchain_impl.go b/core/blockchain_impl.go index 28f2cd904..6e7c2ccf9 100644 --- a/core/blockchain_impl.go +++ b/core/blockchain_impl.go @@ -3186,7 +3186,13 @@ func (bc *BlockChainImpl) isInitTiKV() bool { func (bc *BlockChainImpl) tikvPreemptMaster(fromBlock, toBlock uint64) bool { for { // preempt master - if ok, _ := bc.redisPreempt.TryLock(60); ok { + lockType, _ := bc.redisPreempt.TryLock(60) + switch lockType { + case redis_helper.LockResultRenewalSuccess: + return true + case redis_helper.LockResultSuccess: + // first to master + bc.validatorListByDelegatorCache.Purge() return true } diff --git a/internal/tikv/redis_helper/lock.go b/internal/tikv/redis_helper/lock.go index 6f92b7acc..a9d15ac93 100644 --- a/internal/tikv/redis_helper/lock.go +++ b/internal/tikv/redis_helper/lock.go @@ -4,10 +4,19 @@ import ( "context" "crypto/rand" "encoding/base64" - + "errors" "github.com/go-redis/redis/v8" ) +type LockResult int + +const ( + _ LockResult = iota + LockResultSuccess + LockResultRenewalSuccess + LockResultFail +) + type RedisPreempt struct { key string password string @@ -31,10 +40,15 @@ func (p *RedisPreempt) init() { _, _ = rand.Read(byt) p.password = base64.StdEncoding.EncodeToString(byt) p.lockScript = redis.NewScript(` - if redis.call('get',KEYS[1]) == ARGV[1] then - return redis.call('expire', KEYS[1], ARGV[2]) - else - return redis.call('set', KEYS[1], ARGV[1], 'ex', ARGV[2], 'nx') + local val = redis.call('get', KEYS[1]) + if (val==nil or (type(val) == "boolean" and not val)) then + redis.call('set', KEYS[1], ARGV[1], 'ex', ARGV[2]) + return 'LockResultSuccess' + elseif (val == ARGV[1]) then + redis.call('expire', KEYS[1], ARGV[2]) + return 'LockResultRenewalSuccess' + else + return 'LockResultFail' end `) p.unlockScript = redis.NewScript(` @@ -47,10 +61,23 @@ func (p *RedisPreempt) init() { } // TryLock attempt to lock the master for ttlSecond -func (p *RedisPreempt) TryLock(ttlSecond int) (ok bool, err error) { - ok, err = p.lockScript.Run(context.Background(), redisInstance, []string{p.key}, p.password, ttlSecond).Bool() - p.lastLockStatus = ok - return +func (p *RedisPreempt) TryLock(ttlSecond int) (result LockResult, err error) { + ret, err := p.lockScript.Run(context.Background(), redisInstance, []string{p.key}, p.password, ttlSecond).Text() + if err != nil { + return LockResultFail, err + } + switch ret { + case "LockResultRenewalSuccess": + p.lastLockStatus = true + return LockResultRenewalSuccess, nil + case "LockResultSuccess": + p.lastLockStatus = true + return LockResultSuccess, nil + case "LockResultFail": + return LockResultFail, nil + default: + return LockResultFail, errors.New("fixme: unknown return") + } } // Unlock try to release the master permission From 0dcfeb94887b76a036ab98eba28a8cf027b3bf18 Mon Sep 17 00:00:00 2001 From: lutty Date: Thu, 11 Aug 2022 15:24:36 +0800 Subject: [PATCH 2/2] goimports --- internal/tikv/redis_helper/lock.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/tikv/redis_helper/lock.go b/internal/tikv/redis_helper/lock.go index a9d15ac93..3456906b1 100644 --- a/internal/tikv/redis_helper/lock.go +++ b/internal/tikv/redis_helper/lock.go @@ -5,6 +5,7 @@ import ( "crypto/rand" "encoding/base64" "errors" + "github.com/go-redis/redis/v8" )