Be a positive person

Code, fix bugs, improve yourself

I have a paradise, facing programming, spring flowers!

= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

Interested in artificial intelligence partners, share a my friend’s artificial intelligence tutorial. Zero basis! Easy to understand! Funny humor! You can see if it helps you, click here to see the tutorial.

= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

A: the preface

I encountered such a problem in the actual environment, distributed generation ID problem! Because of business logic problems, I have a method to generate id based on business id + ID as the unique value! Uuids are incremented, starting at 1, and synchronized on the same machine is ok!

However, synchronized or Lock methods cannot prevent id duplication if the project is running on two machines for business expansion or security purposes!!


To solve the above problem, there are other solutions as follows! (1) : the code of production Id of each machine, key+ Id can be distinguished by machine number before key+ Id — > unique machine number + key+ Id (2) : Use database row lock (a single database is when, how is distributed database will also appear problems), in the need to insert ID table plus row lock, prevent data duplication lead to exceptions! (3) : Use distributed locks

Two: Introduction to distributed locks

There are many articles on distributed locking on the web, but a careful analysis of many of the code can be problematic. The following code snippet is from the blog post:

  • My.oschina.net/91jason/blo…
  • Blog.csdn.net/u010359884/…
public void lock(long timeout) {
        long nano = System.nanoTime();
        timeout *= 1000000;
        final Random r = new Random();
        try {
            while ((System.nanoTime() - nano) < timeout) {
                if (redisTemplate.getConnectionFactory().getConnection().setNX(key.getBytes(), LOCKED.getBytes())) {
                    redisTemplate.expire(key, EXPIRE, TimeUnit.SECONDS);
                    locked = true;
                    logger.debug("add RedisLock[" + key + "].");
                    break;
                }
                Thread.sleep(3, r.nextInt(500));
            }
        } catch (Exception e) {
        }
    }
	
Copy the code

The above code blogger also said: if not for a long time, it will fail to obtain the lock, equivalent to no lock!

There are other things that can go wrong here:

(1) Concurrency: when expire releases locks voluntarily, it may release locks of others.

(2) The Redis service is down and the lock fails, which is equivalent to not locking! It is best to use master/slave + sentry for high availability

Note: pay attention to the above problems when using!!

There is a post: www.cnblogs.com/0201zcr/p/5… This blogger asks and analyzes:

 while(timeout >= 0) { long expires = System.currentTimeMillis() + expireMsecs + 1; String expiresStr = String.valueOf(expires); // Lock expiration timeif (this.setNX(lockKey, expiresStr)) {
                // lock acquired
                locked = true;
                return true; } String currentValueStr = this.get(lockKey); // Time in redisif(currentValueStr ! = null && long.parselong (currentValueStr) < system.currentTimemillis ()) { Lock is expired String oldValueStr = this.getSet(lockKey, expiresStr); // Lock is expired String oldValueStr = this.getSet(lockKey, expiresStr); // Only one thread can get the last set time because jedis.getSet is synchronizedif(oldValueStr ! = null && oldValueStr. Equals (currentValueStr)) {// Prevent the lock from being deleted by mistake (because the key is the same). // Required lock locked = // Required lock acquired locked = // Required lock acquired locked =true;
                    return true; } } timeout -= DEFAULT_ACQUIRY_RESOLUTION_MILLIS; With random time delay / * 100 milliseconds, here may be a little bit better, can prevent the occurrence of hunger process, i.e., when arrived at multiple processes at the same time, there will be only one process gets the lock, other all use the same frequency to try, to some behind, also with the same frequency application locks, this will probably lead to front to lock are not being met. */ thread. sleep(DEFAULT_ACQUIRY_RESOLUTION_MILLIS); }Copy the code

Compared with the first one, this improves the problem of deleting the key by mistake, but it is necessary to set the timeout time reasonably (to understand the specific lock business), otherwise, it will also make the lock invalid.

Three: Redisson distributed lock introduction and simple use

Redisson can be found at github.com/redisson/re… Learn here!

Here I say the problems to pay attention to when using:

1: Redis 2.8 or above and Java1.6+ or above are supported. Choose the right version for your environment!

2-2. 8.1 redisson need to use netty jars, otherwise an error: Hopper: Java. Lang. NoClassDefFoundError: IO/netty/channel/EventLoopGroup.

Redisson 3:2.8.1 requires Jackson 2.5+, otherwise error bjectMapper.addMixIn method not fond.

I wrote a simple example and tested it myself, using the Redis master-slave + Sentinel mode! Demo directory structure, specific source CODE I put on Github, address: github.com/dufyun/lear…

Note: you must first install Redis service here, if not installed Redis service, please refer to this article: blog.csdn.net/u010648555/… If the Redis service is installed on the server, please modify the Redis address and port in the code! Otherwise it won’t work!

Run this class UUidGeneratorLockTest to see the effect! I also summarized the test results in readme.txt!

If you have any questions in the process of testing and learning, you can contact me at any time, or add the left group or QQ to discuss with each other! Thank you very much!

Four:

In this era of information explosion and mutual reference between various technical blog posts, real problems may not be exposed, and really good articles still need to be identified! (I also refer to some articles myself, but I always carry out some self-verification, one is for accuracy, one is to deepen my knowledge)

I also want to reflect, I have written some blog posts before, is also encountered problems, go to the Internet to search for some solutions, many solutions are indeed theoretically able to solve the current problems, then to investigate, you will find a lot of incomplete!

Think more, test more! Make your code more efficient, robust, and secure!

Five: refer to blog posts

Redis implements distributed lock global lock – Distributed lock RLock in Redis client Redisson implements distributed lock in several ways


Thank you for reading, if you think this blog is helpful to you, please like or like, let more people see! I wish you happy every day!



No matter what you do, as long as you stick to it, you will see the difference! On the road, neither humble nor pushy!

I wish you and I can become the best of themselves on the way of life, to become an independent person

© Alfayun who is getting better every day