High concurrency, rush to buy

Posted by phonydream on Thu, 23 Apr 2020 18:07:48 +0200

The scene of students choosing courses is similar to that of buying train tickets. Baidu summed up four ways

1. Thread lock. With synchronized, the performance drops sharply. java itself is multithreaded. It's not a wise choice to use it as a single thread. At the same time, if you add synchronized to distributed deployment, you cannot control concurrency.

2. Database lock. Optimistic lock, pessimistic lock. Based on the database optimistic lock face scenario, the concurrency is low and the user activity is low, It mainly focuses on the read-write ability of the Database disk. The concurrent ability is 300-700. With the improvement of the hard disk speed, it may be improved.

3. Cache (asynchronous write based on memory database) redis or memcached

4.Using message middleware and cache

Based on Redis

import java.util.List;

import java.util.Random;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

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

public class MyRunnable implements Runnable {
    String watchkeys = "total"; //Monitoring keys
    int total; //Total items
    Jedis redis = new Jedis("");
    String userinfo;

    public MyRunnable() {

    public MyRunnable(String userinfo, int count) {
        this.userinfo = userinfo;
        this.total = count;

    public static void main(String[] args) {
        int total = 50;
        final Jedis redis = new Jedis("");
        redis.set("total", String.valueOf(total)); //Set the total number of items
        //redis.del("setsucc", "setfail");
        //Create users, set the total number of items, and then start to rush
        ExecutorService executor = Executors.newFixedThreadPool(20); //Maximum concurrency (⊙ o ⊙)
        for (int i = 0; i < 1000; i++) { //Number of people to be snapped up
            executor.execute(new MyRunnable("user" + getRandomString(6),

    public void run() {
        int num = Integer.valueOf(redis.get(watchkeys));
        if (num >= 1 && num <= total) {
            Transaction tx = redis.multi(); //Open transaction
            tx.incrBy(watchkeys, -1); //Increment to - 1
            List list = tx.exec(); //Commit the transaction and return null if the watchkeys are changed at this time
            if (list == null || list.size() == 0) {
                String failUser = "fail" + userinfo;
                String failInfo = "User:" + failUser + "Failed to rush";
                redis.setnx(failUser, failInfo); //Business logic of failed flash purchase
            } else {
                for (Object obj : list) {
                    String succUser = "succ" + obj.toString() + userinfo;
                    String succInfo =
                        "User:" + succUser + "The number of people who have been snapped up is now successful" + (1 - (num - total));
                    redis.setnx(succUser, succInfo); //Business logic of successful flash purchase
        } else {
            String failUser = "kcfail" + userinfo;
            String failInfo = "User:" + failUser + "Product rush failed";
            redis.setnx(failUser, failInfo); //Business logic of failed flash purchase

    private static String getRandomString(int length) {
        String base = "abcdefghijklmnopqrstuvwxyz0123456789";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(base.length());
        return sb.toString();

Topics: Redis Jedis Java Database