In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-25 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
In this issue, the editor will bring you about how SpringBoot uses Redis distributed locks to solve concurrency problems. The article is rich in content and analyzes and describes for you from a professional point of view. I hope you can get something after reading this article.
Problem background
In the current application architecture, many services run in multiple copies to ensure the stability of the service. One service instance is down and other services can still receive requests. However, the multi-copy operation of the service will also lead to some distributed problems. For example, the processing logic of an API is as follows: after receiving the request, query DB to see if there is any relevant data, insert the data if not, and update the data if there is one. In this scenario, if the same N requests are sent concurrently to the backend service instance, the data will be inserted repeatedly:
Solution
To solve the above problems, the general solution is to use distributed locks. The lock in the same process can be solved with the lock in the process, but if the service multi-instance deployment is distributed, the respective processes are independent. In this case, you can set a place to acquire the lock globally. Each process can acquire the global lock in some way. After acquiring the lock, it can execute the relevant business logic code. If you do not get the lock, skip the execution. This global lock is what we call a distributed lock. There are generally three ways to implement distributed locks: 1. Database optimistic lock; 2. Distributed lock based on Redis; 3. Distributed locks based on ZooKeeper.
Here we introduce how to solve the distributed concurrency problem based on Redis distributed locks: Redis acts as a place to acquire global locks. When each instance receives a request, it first acquires the lock from Redis, executes the business logic code after acquiring the lock, and abandons execution if it does not scramble for the lock.
The main principle of implementation is:
Redis locks mainly make use of Redis's setnx command:
Lock command: SETNX key value, when the key does not exist, set the key and return success, otherwise return failure. KEY is the unique identification of the lock, which is generally named according to the business. Value is generally identified by UUID to ensure that locks are not misunderstood.
The unlock command: DEL key, releases the lock by deleting the key-value pair so that other threads can acquire the lock through the SETNX command.
Lock timeout: EXPIRE key timeout, set the key timeout to ensure that even if the lock is not explicitly released, the lock can be released automatically after a certain period of time to prevent resources from being locked forever.
Reliability:
To ensure that distributed locks are available, we need to ensure that the lock implementation meets at least the following four conditions:
Repulsion. At any time, make sure that only one thread on one machine can hold the lock
There is no deadlock. Even if one client crashes while holding the lock and does not unlock it actively, it can ensure that other clients can add the lock.
It is non-obstructive. Once you can't get the lock, you will immediately return to the lock failure.
Locking and unlocking must be the same client, and the client cannot unlock the lock added by others.
SpringBoot integration uses Redis distributed locks
A RedisLock tool class is written, which is used for locking before business logic execution and unlocking operation after business logic execution. The locking operation here may not be perfect. There are two atomicity problems: locking and lock expiration. If the SpringBoot version is 2.x, you can use the code in the comments to set the lock expiration time at the same time. If the SpringBoot version is below 2.x, it is recommended to use the Lua script to ensure the atomicity of the operation. For simplicity, write like this:
Import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.core.StringRedisTemplate;import org.springframework.data.redis.core.script.DefaultRedisScript;import org.springframework.stereotype.Component;import java.util.ArrayList;import java.util.List;import java.util.concurrent.TimeUnit;/** * @ description: Redis distributed Lock implementation tool Class * @ author: qianghaohao * @ time: 2021-7-19 * / @ Componentpublic class RedisLock {@ Autowired StringRedisTemplate redisTemplate / * * acquire lock * * @ param lockKey lock * @ param identity identity (ensure that the lock will not be released by others) * @ param expireTime lock expiration time (in seconds) * @ return * / public boolean lock (String lockKey, String identity, long expireTime) {/ / because our current springboot version is relatively low, 1.5.9 Therefore, the following writing method / / return redisTemplate.opsForValue () .setIfAbsent (lockKey, identity, expireTime, TimeUnit.SECONDS) is not supported. If (redisTemplate.opsForValue () .setIfAbsent (lockKey, identity)) {redisTemplate.expire (lockKey, expireTime, TimeUnit.SECONDS); return true;} return false } / * * release lock * * @ param lockKey lock * @ param identity identity (ensure that the lock will not be released by others) * @ return * / public boolean releaseLock (String lockKey, String identity) {String luaScript = "if" + "redis.call ('get'") KEYS [1]) = ARGV [1] "+" then "+" return redis.call ('del', KEYS [1]) "+" else "+" return 0 "+" end " DefaultRedisScript redisScript = new DefaultRedisScript (); redisScript.setResultType (Boolean.class); redisScript.setScriptText (luaScript); List keys = new ArrayList (); keys.add (lockKey); Object result = redisTemplate.execute (redisScript, keys, identity); return (boolean) result;}} usage example
Only the key usage code is posted here. Note: the key of the lock is named according to its own business logic and can uniquely mark the same request. Value is set to UUID here to ensure that the lock is released correctly (only the locks you add).
@ Autowiredprivate RedisLock redisLock; / / redis distributed lock String redisLockKey = String.format ("% s:docker-image:%s", REDIS_LOCK_PREFIX, imageVo.getImageRepository ()); String redisLockValue = UUID.randomUUID () .toString () Try {if (! redisLock.lock (redisLockKey, redisLockValue, REDIS_LOCK_TIMEOUT)) {logger.info ("redisLockKey [" + redisLockKey + "] already exists and does not perform image insertion and update"); result.setMessage ("frequent new images, retry later, lock occupation"); return result }. / / execute business logic catch (Execpion e) {. / / exception handling} finally {/ / release lock if (! redisLock.releaseLock (redisLockKey, redisLockValue)) {logger.error ("release redis lock [" + redisLockKey + "] failed) } else {logger.error ("release of redis locks [" + redisLockKey + "] succeeded");}} above is how SpringBoot uses Redis distributed locks to solve concurrency problems. If you happen to have similar doubts, please refer to the above analysis to understand. If you want to know more about it, you are welcome to follow the industry information channel.
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.