Redis optimistic lock achieves high concurrency spike

Editor:
Author: peony boy
link: https: //www.jianshu.com/p/06f1bce98451

In the case of limited flash purchase, you will definitely encounter the problem of the number of successful purchases exceeding the limit and the high concurrency that affects the system performance

1. Although the database lock can be used to avoid the problem of exceeding the limit. But in the case of large concurrency, it will greatly affect database performance.
2. In order to avoid concurrent operation of the database, we can use queues to limit, but the amount of concurrency will increase the queue memory instantly.
3. We can use pessimistic locks to achieve this, but this Will cause users to wait, slow response and bad experience

So we can use redis to implement optimistic locking

1、利用redis的watch功能,监控这个redisKey的状态值
2、获取redisKey的值
3、创建redis事务
4、给这个key的值+1
5、然后去执行这个事务,如果key的值被修改过则回滚,key不+1

Here I use java to achieve, I opened 20 threads to simulate 10,000 concurrent people to snap up the purchase, other languages ​​are the same implementation principle.

package com.kuang;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;

import java.util.List;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Created by zjl
 * 2021/2/18
 **/
public class 秒杀 {
    
    
    public static void main(String[] arg){
    
    
        String redisKey = "redisTest";
        ExecutorService executorService = Executors.newFixedThreadPool(20);
        try {
    
    
            Jedis jedis = new Jedis("127.0.0.1",6379);
            jedis.auth("123456");
            jedis.set(redisKey,"0");
            jedis.close();
        }catch (Exception e){
    
    
            e.printStackTrace();
        }

        for (int i=0;i<10000;i++){
    
    
            executorService.execute(()->{
    
    
                Jedis jedis1 = new Jedis("127.0.0.1",6379);
                jedis1.auth("123456");
                try {
    
    
                    jedis1.watch(redisKey);
                    String redisValue = jedis1.get(redisKey);
                    int valInteger = Integer.valueOf(redisValue);
                    String userInfo = UUID.randomUUID().toString();
                    if (valInteger<20){
    
    
                        Transaction transaction = jedis1.multi();
                        transaction.incr(redisKey);
                        List list = transaction.exec();
                        if (list!=null){
    
    
                            System.out.println("用户:"+userInfo+",秒杀成功!当前成功人数:"+(valInteger+1));
                        }else {
    
    
                            System.out.println("用户:"+userInfo+",秒杀失败");
                        }
                    }else {
    
    
                        System.out.println("已经有20人秒杀成功,秒杀结束");
                    }
                }catch (Exception e){
    
    
                    e.printStackTrace();
                }finally {
    
    
                    jedis1.close();
                }
            });
        }
        executorService.shutdown();
    }
}

Insert picture description here
If there is anything wrong, please actively point it out!

Guess you like

Origin blog.csdn.net/qq_41347385/article/details/113851822