One click to understand distributed lock 3

Posted by hmogan on Fri, 14 Jan 2022 18:20:45 +0100

Distributed lock - Implementation Based on Redisson aspect

We have learned from the previous two articles Implementation based on Database as well as Redis based implementation We learned about the implementation of distributed locks from the database and Redis levels. In this article, we learn about distributed locks from the aspect of redistribution.

At present, Redisson meets all the conditions of distributed lock and must be the first choice! In real use, we must use the API reasonably according to the actual situation, Redisson view address . It mainly includes configuration, API introduction, etc., which is very convenient.

Next, we need to deal with the page, as follows:
Demonstrate with resources from previous learning in Spring Cloud:
Register the service in Eureka cluster:
At present, Eureka has published articles. If you don't understand, please Reference articles.

Distribute the request to the system we need through OpenFeign+Ribbon:

At present, Ribbon has published articles. If you don't understand, please Reference articles . If OpenFeign doesn't understand it, a follow-up article will briefly introduce it.

The specific business procedures to be executed are order8002 and order8003

Take the 8002 project as an example:

Import Redisson POM file:

   <!--redissson introduce-->
        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson</artifactId>
            <version>3.16.7</version>
        </dependency>

Import Redisson basic information configuration file:

@Data
@ConfigurationProperties(prefix = "redisson")
public class RedissonProperties {

    // Single node address
    private String address;
    // password
    private String password;
    // Cluster address
    private String[] sentinelAddresses;
    // The name of the primary server
    private String masterName;
    // Database number
    private int database = 0;
    // Command wait timeout
    private int timeout = 3000;
    // Connection pool size
    private int connectionPoolSize = 64;
    // Minimum number of free connections
    private int connectionMinimumIdleSize=10;
    // Connection pool size from node
    private int slaveConnectionPoolSize = 250;
    // Primary node connection pool size
    private int masterConnectionPoolSize = 250;
}

Redisson Config file:

@Configuration
@ConditionalOnClass(Config.class)
@EnableConfigurationProperties(RedissonProperties.class)
public class RedissonAutoConfiguration {

    @Autowired
    private RedissonProperties redssionProperties;

    /**
     * Single machine mode automatic assembly
     * @return
     */
    @Bean
    @ConditionalOnProperty(name="redisson.address")
    RedissonClient redissonSingle() {
        Config config = new Config();
        SingleServerConfig serverConfig = config.useSingleServer()
                .setAddress(redssionProperties.getAddress())
                .setTimeout(redssionProperties.getTimeout())
                .setConnectionPoolSize(redssionProperties.getConnectionPoolSize())
                .setConnectionMinimumIdleSize(redssionProperties.getConnectionMinimumIdleSize());

        if(StringUtils.isNotBlank(redssionProperties.getPassword())) {
            serverConfig.setPassword(redssionProperties.getPassword());
        }

        return Redisson.create(config);
    }

    /**
     * Sentinel mode automatic assembly
     * @return
     */
    @Bean
    @ConditionalOnProperty(name="redisson.master-name")
    RedissonClient redissonSentinel() {
        Config config = new Config();
        SentinelServersConfig serverConfig = config.useSentinelServers()
                .addSentinelAddress(redssionProperties.getSentinelAddresses())
                .setMasterName(redssionProperties.getMasterName())
                .setTimeout(redssionProperties.getTimeout())
                .setMasterConnectionPoolSize(redssionProperties.getMasterConnectionPoolSize())
                .setSlaveConnectionPoolSize(redssionProperties.getSlaveConnectionPoolSize());
        if(StringUtils.isNotBlank(redssionProperties.getPassword())) {
            serverConfig.setPassword(redssionProperties.getPassword());
        }
        return Redisson.create(config);
    }
}

Specific use of the properties file:

# redisson standalone
redisson.address=redis://127.0.0.1:6379
redisson.password=*****

# redisson sentinel mode
#redisson.master-name=
#redisson.password=
#redisson.sentinel-addresses=a,b

After completing the above steps, we have configured it. Next, we will simply use Redisson. The specific methods and rules are basically the same as our previous Lock ideas. Remember: when the Lock is used up, you must unlock it, otherwise it will cause deadlock!

Set 5 tickets to issue tickets. Simple cases are as follows:

    @Autowired
    private RedissonClient redissonClient;

    private String KEY = "RedissonLock";
    private int waitTime = 20;
    private int leaseTime = 1000;

    @RequestMapping("/getMyStaff")
    public void getMyStaff(@RequestParam("staffIdNo") String staffIdNo){
        System.out.println("Enter 8002....");
        RLock lock = redissonClient.getLock(KEY);
        try {
            //When executing a specific business, you need to try to obtain a lock
            //Try locking and wait for waitTime seconds at most. After locking, leaseTime seconds will unlock automatically
            boolean b = lock.tryLock(waitTime, leaseTime, TimeUnit.SECONDS);
            if (b){
                //Specific business
                Staff staff = staffService.getStaff(staffIdNo);
                if (Integer.valueOf(staff.getStaffIphone())>0){
                    staff.setStaffIphone(Integer.valueOf(staff.getStaffIphone()) - 1+"");
                    staffService.updateStaff(staff);
                }else{
                    System.out.println("sorry,The tickets are sold out...");
                }
                Thread.sleep(1000);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
            System.out.println("Unlock succeeded!");
        }
    }

The entity type inside is not important, just know the idea!

Log on 8002 server:

Log on 8003 server:

The above is the simple use of Redisson. Specifically, the corresponding locks must be used reasonably according to the business and API! The locks here are special. You can use the locks that meet the requirements for the business!

Topics: Java Back-end Multithreading Distribution redisson