编程知识 cdmana.com

How to design redis distributed lock of alihuawei and other large factories?

1 Local lock

Commonly used is synchronize or Lock etc. JDK The lock that comes with it , Can only lock the current process , Only for single architecture services .
In the distributed multi service instance scenario, distributed lock must be used

2 Distributed lock

2.1 The principle of distributed lock

Toilet pit theory

You can go to one place at the same time “ Occupy the pit ”:

  • occupy , Just execute the logic
  • Or wait for , Until the lock is released
    You can spin by spinning

“ Occupy the pit ” You can go to Redis、DB、 Anywhere all services can access .

2.2 Distributed lock evolution

A stage

//  Occupy distributed lock , Go to redis Occupy the pit 
Boolean lock = redisTemplate.opsForValue().setIfAbsent("lock", "111");
if(lock) {
    
	// Locking success ...  Executive business 
	Map<String, List<Catelog2Vo>> dataFromDb = getDataFromDb();
	redisTemplate . delete( key: "lock");//fHßti
	return dataF romDb ;
} else {
    
	//  Locking failed , retry .synchronized()
	//  Sleep 100ms retry 
	//  The spin 
	return getCatalogJsonFromDbwithRedisLock();
}

Problem scenario

  • setnx Take the pit , But the business code is abnormal or the program is down during execution , That is, the lock logic is not deleted successfully , Lead to a deadlock
    Solution : Set the automatic expiration of locks , Even if it's not deleted , It will be deleted automatically .

Stage two

// 1.  Occupy distributed lock , Go to redis Occupy the pit 
Boolean lock = redisTemplate.opsForValue().setIfAbsent( "lock", "110")
if(lock) {
    
	//  Locking success ... Executive business 
	
	//  A sudden power failure 
	
	// 2.  Set expiration time 
	redisTemplate.expire("lock", timeout: 30, TimeUnit.SECONDS) ;
	Map<String, List<Catelog2Vo>> dataFromDb = getDataFromDb();
	// Delete lock 
	redisTemplate. delete( key; "lock");
	return dataFromDb;
} else {
    
	//  Locking failed ... retry . synchronized ()
	//  Sleep 100ms retry 
	//  The way you spin 
	return getCatalogJsonF romDbWithRedisLock();
}

Problem scenario

  • setnx Set it up , About to set the expiration time , Downtime , Deadlock again
    Solution : Setting expiration time and occupancy must be atomic .redis Support use setNxEx command

Stage three

// 1.  Distributed lock takes up the pit 
Boolean lock = redisTemplate.opsForValue().setIfAbsent("lock", "110", 300, TimeUnit.SECONDS);
if(lock)(
	//  Locking success , Executive business 
	
	// 2.  Set expiration time , It must be used with locking as an atomic operation 
	// redisTemplate. expire( "lock", з0, TimeUnit.SECONDS);
	Map<String, List<Catelog2Vo>> dataFromDb = getDataFromDb();
	//  Delete lock 
	redisTemplate.delete( key: "lock")
	return dataFromDb;
else {
    
	//  Locking failed , retry 
	//  Sleep 100ms retry 
	//  The spin 
	return getCatalogJsonFromDbithRedislock()
}

Stage four

It's got lockvalue , With UUID, But it's overdue. Now ! Others get the lock and set the new value , therefore if And then I deleted someone else's lock !! In other words, deleting a lock is not an atomic operation .

Map<String, List<Catelog2Vo>> dataFromDb = getDataFromDb();
String lockValue = redisTemplate.opsForValue().get("lock");
if(uuid.equals(lockValue)) {
    
	//  Remove my own lock 
	redisTemplate.delete("lock");
}

Problem scenario

  • If it happens to be the current value , About to delete the lock , Lock expired , Someone else has set the new value successfully . That's someone else's lock .
  • Solution
    Deleting a lock must guarantee atomicity . Use redis+Lua Script .

Stage five

  • Make sure to lock / Unlocking is all atomic
String script = 
	"if redis.call('get', KEYS[1]) == ARGV[1] 
		then return redis.call('del', KEYS[1]) 
	else 
		return 0 
	end";

Make sure you lock it 【 placeholder + Expiration time 】 And remove locks 【 Judge + Delete 】 The atomicity of . The harder things , Automatic renewal of locks .

summary

In fact, the more troublesome things , And automatic renewal of locks . So whether it's a big factory or a small and medium-sized company , We all chose to solve these problems directly Redisson! Don't make wheels again , But it's also important to know what problems the framework solves , It is convenient for us to quickly check and locate when we encounter problems .
Next we'll start redisson Explain how he did it ~

版权声明
本文为[The official account -JavaEdge]所创,转载请带上原文链接,感谢
https://cdmana.com/2021/04/20210421231755196n.html

Scroll to Top