How to solve the oversold problem under gaobingfa

Keywords: html5 html css

Current limiting: it is solved by configuring sentinel

Queue, asynchronous

                   

  Through locking synchronized or lock, the problem is that the scope of synchronized is a single jvm instance, the cluster distribution fails, and the serial efficiency decreases after locking a single jvm

Distributed locks can be used, but distributed locks are too cumbersome and their performance is degraded.

 

 

Sometimes, in order to solve the ABA problem, you need to add a version number field, and then judge whether the version number is the same.

Multiple sql scenarios for inventory deduction

First kind  :   update product set stock=stock-1 where id = 1 and stock>0

The second type: update product set stock=stock-1 where stock = #{inventory originally queried} and id = 1 and stock > 0

The third type: update product set stock = stock-1, versionin = version + 1, where id = 1 and stock > 0 and
Version = #{originally queried version number}

The core is to solve the oversold problem and prevent the inventory from being negative:

For scheme 1: on the premise that id is the primary key index, if only one inventory is reduced each time, it can be used. Only data security verification can effectively reduce inventory, improve performance, avoid a large number of invalid sql, and the operation can be successful as long as there is inventory

Scenario: number fetcher in high concurrency scenario, coupon issuance and inventory deduction

Scheme 2: use the conditions of the business itself as an optimistic lock, but there is an ABA problem. Compared with scheme 3, the advantage is that you don't need to increase the version number. If you only deduct inventory and don't care about ABA, you can use it.

Scheme 3: adding the version number is mainly to solve the ABA problem. After reading the data, the data has been tampered with before updating, and the version can only be incremented.

Scenario: Commodity spike, coupon method, need to record the business before and after inventory operation.

Personal super coupon

In the process of receiving coupons, the verification sum is saved to the database without distribution lock, resulting in over receiving coupons;

Methods to implement distributed locks include mysql, redis and zookeeper

  redisson framework for distributed locks

 Distributed lockhttps://github.com/redisson/redisson/wiki/%E7%9B%AE%E5%BD%95

  Using distributed lock plug-ins

1. Import one or two to the common module

      <!--Distributed lock-->
        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson</artifactId>
            <version>3.10.1</version>

  2. Configure distributed locks in commoon

@Configuration
@Data
public class APPConfig {

    @Value("${spring.redis.host}")
    private String redisHost;

    @Value("${spring.redis.port}")
    private String redisPort;

    @Value("${spring.redis.password}")
    private String redispwd;

    /**
     * redisson for configuring distributed locks
     * @return
     */
    @Bean
    public RedissonClient redissonClient(){
        Config config = new Config();
        // Stand alone mode
        config.useSingleServer().setPassword(redispwd).setAddress("redis://"+redisHost+":"+redisPort);
        // Cluster mode
       // config.useClusterServers().addNodeAddress("127.0.0.1:7004", "127.0.0.1:7001");
        RedissonClient redissonClient = Redisson.create(config);
        return redissonClient;
    }
}

3. Using distributed locks

 @GetMapping("lock")
    public JsonData testLock(){

        // Distributed locks are the same as this and
//        ReentrantLock reentrantLock = new ReentrantLock();
//        reentrantLock.lock();
//        reentrantLock.unlock();

        RLock lock = redissonClient.getLock("lock:coupon:1");
//        //Blocking waiting time
//        lock.lock(10, TimeUnit.SECONDS);

        lock.lock();

        //Business logic
        try{
            log.info("Lock successfully, process business logic"+Thread.currentThread().getId());
            TimeUnit.SECONDS.sleep(20);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            log.info("Unlock succeeded");
            lock.unlock();
        }

        return JsonData.buildSuccess();
    }

  How redisson resolves that the expiration time is less than the execution time of the business:

Adopt the way of watchdog;

              

  The watchdog's check lock timeout is 30s.

     // When multiple threads enter, they will be blocked. There is a watchdog waiting for the lock to be released. The default is 30s
        rlock.lock();
        
     // After locking for 10s, it expires, and there is no watch dog function
        rlock.lock(10,TimeUnit.SECONDS);

 

  When setting transactions in a project, first start transaction management in the startup class, and then add transaction annotations to the transaction methods.

 

Posted by Fractal on Mon, 20 Sep 2021 02:32:46 -0700