In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Database >
Share
Shulou(Shulou.com)06/01 Report--
What the editor wants to share with you this time is to explain in detail how redis implements distributed locks. The article is rich in content. Interested friends can learn about it. I hope you can get something after reading this article.
Preface
With the continuous expansion of the system, distributed lock is the most basic guarantee. Unlike multithreading on a single machine, it is distributed across multiple machines. Shared variables for threads cannot span machines.
To ensure that one can only be operated by the same thread in a high concurrency scenario, java concurrent processing provides ReentrantLock or Synchronized for mutex control. But this only works in a stand-alone environment. We implement distributed locks in about three ways.
Redis implements distributed Lock Database realizes distributed Lock zk implements distributed Lock
Today we introduce the implementation of distributed locks through redis. In fact, these three belong to the same category as java. All belong to the external lock of the program.
Principle analysis
The above three kinds of distributed locks control whether to release or reject by locking and unlocking each request on their own basis. The redis lock is based on the setnx command it provides. Setnx if and only if key does not exist. If a given key already exists, the setnx does not do anything. Setnx is an atomic operation. Compared with database distribution, redis memory is lightweight. So redis distributed locks have better performance.
Realize
The principle is simple. Combined with the springboot project, we realize a set of cases of interface inventory locking in the form of annotations.
Write notes
We write notes. It is convenient for us to add comments on the interface to provide interception information.
/ * @ author Zhang Xinhua * @ version V1.0 * @ Package com.ay.framework.order.redis.product * @ date, 0026 10:29 * @ Copyright ©2020 Anyuan Technology Co., Ltd. * / @ Target (ElementType.METHOD) @ Retention (RetentionPolicy.RUNTIME) @ Documented@Inheritedpublic @ interface StockLock {/ * * @ author zxhtom * @ Description lock key prefix * @ Date 15:25 March 25, 2020 0025 * @ Param [] * @ return java.lang.String * / String prefix () default "" The delimiter * @ Date of / * * @ author zxhtom * @ Description key 15:27 March 25, 2020, 0025 * @ Param [] * @ return java.lang.String * / String delimiter () default ":" } / * @ author Zhang Xinhua * @ version V1.0 * @ Package com.ay.framework.order.redis.product * @ date, 0026 11:09 * @ Copyright ©2020 Angyuan Technology Co., Ltd. * / @ Target ({ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD}) @ Retention (RetentionPolicy.RUNTIME) @ Documented@Inheritedpublic @ interface StockParam {/ * @ author zxhtom * @ Description key * @ Date 11:11 March 26, 2020 0026 * @ Param [] * @ return java.lang.String [] * / String [] names () default {""} }
Interceptor intercept
The key to the implementation of redis distributed lock is the writing of interceptor. The above comments are only an aid to interception.
@ Around ("execution (public * * (..)) & & @ annotation (com.ay.framework.order.redis.product.StockLock)")
Intercept StockLock annotations through springboot's Around. Through interception, we can get the interception method, parameters, and the parameters of the lock we need.
We get the name of the lock that needs to be called [a] here and then decrement the redis through the atomic operation of the key.
In order to make it convenient for us to update the inventory when we reduce the inventory. We need another lock before we reduce our inventory. This lock is called [a_key].
In other words, if our interface wants to access, we must acquire the [a] lock, and to get the [a] lock, we need to reduce inventory. You need to acquire [a_key] locks before reducing inventory.
After getting the lock and processing the logic, we need to release the corresponding lock.
RedisAtomicLong entityIdCounter = new RedisAtomicLong (lockKey, redisTemplate.getConnectionFactory ()); if (redisTemplate.hasKey (CoreConstants.UPDATEPRODUCTREDISLOCKKEY + lockKey)) {/ / indicates that the inventory information of lockKey has changed. The transaction throw new BusinessException ("inventory change") cannot be made at this time. Cannot be traded ");} Long increment = entityIdCounter.decrementAndGet (); if (increment > = 0) {try {Object proceed = pjp.proceed ();} catch (Throwable throwable) {/ / the occupied resources need to be released back to the resource pool while (! redisLock.tryGetLock (CoreConstants.UPDATEPRODUCTREDISLOCKKEY + lockKey,")) {} / / indicates that the inventory information of lockKey has changed. Long l = entityIdCounter.incrementAndGet (); if (l) cannot be traded at this time
< 1) { redisTemplate.opsForValue().set(lockKey,1); } redisLock.unLock(CoreConstants.UPDATEPRODUCTREDISLOCKKEY + lockKey); throwable.printStackTrace(); } } else { redisTemplate.opsForValue().set(lockKey,0); throw new BusinessException("库存不足!无法操作"); } 因为我们上锁就需要释放锁。但是程序在中途处理业务是发生异常导致没有走到释放锁的步骤。这个时候就导致我们的分布式锁一直被锁。俗称【死锁】。为了避免这种场景的发生。我们常常在上锁的时候给一个有效期。有效期已过自动释放锁。这个特性恰好和redis的过期策略不摩尔和。 上述提及工具 RedisLock public Boolean tryGetLock(String key , String value) { return tryGetLock(key, value, -1, TimeUnit.DAYS);}public Boolean tryGetLock(String key , String value, Integer expire) { return tryGetLock(key, value, expire, TimeUnit.SECONDS);}public Boolean tryGetLock(String key , String value, Integer expire , TimeUnit timeUnit) { ValueOperations operations = redisTemplate.opsForValue(); if (operations.setIfAbsent(key, value)) { //说明 redis没有该key , 换言之 加锁成功 设置过期时间防止死锁 if (expire >0) {redisTemplate.expire (key, expire, timeUnit);} return true;} return false;} public Boolean unLock (String key) {return redisTemplate.delete (key);}
StockKeyGenerator
@ Component () @ Primarypublic class StockKeyGenerator implements CacheKeyGenerator {@ Override public String getLockKey (ProceedingJoinPoint pjp) {/ / get method signature MethodSignature signature = (MethodSignature) pjp.getSignature (); Method method = signature.getMethod (); / / get method cacheLock comment StockLock stockLock = method.getAnnotation (StockLock.class); / / get method parameter Object [] args = pjp.getArgs (); Parameter [] parameters = method.getParameters (); StringBuilder builder = new StringBuilder () For (int I = 0; I
< parameters.length; i++) { StockParam stockParam = parameters[i].getAnnotation(StockParam.class); Object arg = args[i]; if (arg instanceof Map) { Map temArgMap = (Map) arg; String[] names = stockParam.names(); for (String name : names) { if (builder.length() >0) {builder.append (stockLock.delimiter ());} builder.append (temArgMap.get (name));} return builder.toString ();}}
Analysis of problems
The above analysis of a deadlock scenario, in theory, a deadlock we redis distributed lock to solve the distributed problem. But there will still be problems. The following is a list of the problems encountered by the editor.
Business processing time > lock expiration time
A thread acquires the lock and starts business processing with 8s
In 8s, the period of validity of the lock is 5s. After the lock expires, that is, 6S, b thread enters and starts to acquire the lock when b can acquire the new lock. There is a problem at this time.
Suppose that the b thread business processing only needs 3s, but because the a thread releases the lock, although the b thread does not release the lock and the b lock does not expire at 8s, there is no lock at this time. As a result, C threads can also enter
After reading this article on explaining how redis implements distributed locks, if you think the article is well written, you can share it with more people.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.