In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-04-01 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Database >
Share
Shulou(Shulou.com)06/01 Report--
Editor to share with you how to use redis to achieve distributed locks. I hope you will learn a lot after reading this article. Let's discuss it together.
Using Redis to realize distributed Lock
Introduction to redis characteristics
1. Supports rich data types, such as String, List, Map, Set, ZSet, etc.
2. Support data persistence, RDB and AOF.
3. Supports cluster working mode and has strong fault tolerance in partitions.
4. Single thread, sequential processing commands
5. Support transactions
6. Support publish and subscribe
Redis implements distributed locks using the SETNX command:
SETNX key value
Set the value of key to value if and only if key does not exist.
If a given key already exists, the SETNX does not take any action.
SETNX is an abbreviation for "SET if Not eXists" (or SET if it does not exist).
Available version: > = 1.0.0 time complexity: O (1) return value:
If the setting is successful, return 1.
Setting failed and 0 was returned.
Redis > EXISTS job # job does not exist (integer) 0redis > SETNX job "programmer" # job setting success (integer) 1redis > SETNX job "code-farmer" # attempt to overwrite job, failure (integer) 0redis > GET job # not overwritten "programmer"
First, we need to encapsulate a common Redis access utility class. This class requires injection of RedisTemplate instances and ValueOperations instances, and ValueOperations instances are used because the distributed locks implemented by Redis use the simplest String type. In addition, we need to encapsulate three methods, namely setIfObsent (String key, String value), expire (String key, long timeout, TimeUnit unit) and delete (String key), corresponding to the SETNX, expire and del commands of Redis, respectively. The following is the specific implementation of the Redis access utility class:
@ Componentpublic class RedisDao {@ Autowired private RedisTemplate redisTemplate; @ Resource (name= "redisTemplate") private ValueOperations valOpsObj / * if key does not exist, store a key-value, which is equivalent to the SETNX command * @ param key key * @ param value value, and can be empty * @ return * / public boolean setIfObsent (String key, String value) {return valOpsObj.setIfAbsent (key, value) } / * set expiration time for key * @ param key key * @ param timeout time size * @ param unit time unit * / public boolean expire (String key, long timeout, TimeUnit unit) {return redisTemplate.expire (key, timeout, unit) } / * * remove key * @ param key key * / public void delete (String key) {redisTemplate.delete (key);}}
Having completed the implementation of the Redis access tool class, what we need to consider now is how to simulate competitive distributed locks. Because Redis itself supports distributed clustering, you only need to simulate a multithreaded business scenario. The thread pool is used to simulate here. The following is the specific implementation of the test class:
@ RestController@RequestMapping ("test") public class TestController {private static final Logger LOG = LoggerFactory.getLogger (TestController.class); / / distributed lock key private static final String LOCK_KEY = "MyTestLock" defined by log object @ Autowired private RedisDao redisDao; / / @ RequestMapping (value= {"testRedisLock"}, method=RequestMethod.GET) public void testRedisLock () {ExecutorService executorService = Executors.newFixedThreadPool (5) For (int I = 0; I < 5) ExecutorService.submit +) {executorService.submit (new Runnable () {@ Override public void run () {/ / acquire distributed lock boolean flag = redisDao.setIfObsent (LOCK_KEY, "lock") If (flag) {LOG.info (Thread.currentThread () .getName () + ": Redis distributed lock acquired successfully") / / set the expiration time redisDao.expire (LOCK_KEY, 2, TimeUnit.SECONDS) after the lock is acquired successfully Try {LOG.info (Thread.currentThread (). GetName () + ": start processing business"); Thread.sleep (1000) / / Sleep 1000ms simulates processing business LOG.info (Thread.currentThread (). GetName () + ": processing business end") / / delete lock redisDao.delete (LOCK_KEY) after processing business is completed } catch (InterruptedException e) {LOG.error ("handling business exceptions:", e) }} else {LOG.info (Thread.currentThread (). GetName () + ": failed to acquire Redis distributed lock") })
Through the above code, the following questions may arise:
If a thread fails to acquire a distributed lock, why not try to reacquire the lock?
After the thread successfully acquires the distributed lock, the failure time of the lock is set. How to determine the failure time?
After the thread business processing ends, why do you delete the lock?
In view of these questions, we can discuss them.
First, Redis's SETNX command does nothing if key already exists, so the distributed lock implemented by SETNX is not a reentrant lock. Of course, you can also retry n times through your own code or until the distributed lock is acquired. However, this does not guarantee the fairness of the competition, and a thread will block because it has been waiting for a lock. Therefore, the distributed lock implemented by Redis is more suitable for the scenario of writing and reading multiple reads to shared resources.
Second, the failure time of the distributed lock must be set, and the failure time must be greater than the time required for business processing (to ensure data consistency). Therefore, in the test phase, the time required for normal business processing is predicted as accurately as possible, and the failure time is set to prevent deadlock due to some reasons in the business process.
Third, when the business processing is finished, the lock must be deleted.
Setting the distributed lock and setting the failure time for the lock is accomplished through two operating steps, and a more reasonable way is to set the distributed lock and set the expiration time for the lock in one operation. Either they succeed or they all fail. The implementation code is as follows:
/ * Redis access tool class * / @ Componentpublic class RedisDao {private static Logger logger = LoggerFactory.getLogger (RedisDao.class); @ Autowired private StringRedisTemplate stringRedisTemplate / * * set distributed lock * @ param key key * @ param value value * @ param timeout expiration time * @ return * / public boolean setDistributeLock (String key, String value, long timeout) {RedisConnection connection = null; boolean flag = false Try {/ / get a connection connection = stringRedisTemplate.getConnectionFactory () .getConnection (); / / set the expiration time connection.set (key.getBytes (), value.getBytes (), Expiration.seconds (timeout), RedisStringCommands.SetOption.SET_IF_ABSENT) for the lock while setting the distributed lock. Flag = true;} catch (Exception e) {logger.error ("set automic lock error:", e);} finally {/ / close the connection connection.close ();} return flag after use } / * query the expiration time of key * @ param key key * @ param timeUnit time unit * @ return * / public long ttl (String key, TimeUnit timeUnit) {return stringRedisTemplate.getExpire (key, timeUnit) The unit test class * / @ RunWith (SpringRunner.class) @ SpringBootTestpublic class Demo1ApplicationTests {private static final Logger LOG = LoggerFactory.getLogger (Demo1ApplicationTests.class); @ Autowired private RedisDao redisDao; @ Testpublic void testDistributeLock () {String key = "MyDistributeLock" / / set distributed lock, failure time 20s boolean result = redisDao.setDistributeLock (key, "1", 20); if (result) {LOG.info ("set distributed lock successfully"); long ttl = redisDao.ttl (key, TimeUnit.SECONDS) LOG.info ("{} distance failure and {} s", key, ttl);}
Run the unit test class and the results are as follows:
2019-05-15 13 07RV 10.827-set distributed lock successfully 2019-05-15 13Rd 07RV 10.838-MyDistributeLock distance invalidation and 19s have read this article, I believe you have some understanding of the method of using redis to achieve distributed lock, want to know more related knowledge, welcome to follow the industry information channel, thank you for reading!
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.