Lao Kou Yun - advanced java technology stack - martial arts chapter - redis distributed lock implementation to grab red envelopes (article continuous tuning)

Hello, guys! I'm old Kou! No more nonsense. Grab the red envelope with me

catalogue

1. Operation effect diagram (station b - address)

2. Technical architecture

3. Technical selection

4. Business logic (key)

5. Design of distributed lock (personal understanding)

6. Implementation of distributed lock (core code)

1. Operation effect diagram( b station - Address)

redis distributed lock to grab red packets

2. Technical framework

Basic framework: springboot + springcloud

Message queue: rabbitMQ

Data cache: redis

Message push: websocket

3. Technical selection

Why use redis to implement the distributed lock scheme, abandon the synchronized scheme, and adopt the synchronized scheme. The locks held in the distributed system cannot be the same lock (applicable to single applications, not microservice applications). Therefore, this scheme has been discarded

4. Business logic (key)

* Advanced -> use gateway Gateway current limiting -> Token Bucket  + redis,Limit the concurrency and put too many requests into the queue->rabbitmq
* 1.Judge whether there is any left in the red envelope (routine: first redis Read inside, redis No data, then go mysql Query into redis)
* 2.Judge whether the user has robbed the red envelope
* 3.Get the red envelope amount, and write the remaining red envelope number and red envelope amount redis
* 4.Keep the record of robbing red envelopes (put the record into mysql)
* 5.Respond to the front end (call the message service with websocket Push message to front end->The connection must be initialized when the user clicks in)

5. Design of distributed lock (personal understanding)

In the distributed system, service downtime will occur. There are many cases of service downtime, such as insufficient memory, sudden increase of traffic, etc., which will lead to service downtime. Therefore, two points should be considered in the design of distributed locks:

1. Atomicity: it is understood that when a thread holds a lock, other threads can only wait. When the lock is released, other threads have the opportunity to seize the lock. Finally, only one thread will hold the lock. Let me give an example: everyone has the experience of taking an elevator or Ferris wheel. Excluding the full population, press the elevator button at the same time, Everyone has the same probability of being an elevator. Stopping at a certain floor means that the person can be an elevator, and everyone on that floor owns the elevator. The floors of this building can be regarded as threads one by one. The elevator can be roughly regarded as a lock. Especially when eating or getting off work, we all want to do the elevator quickly. This is also a high concurrency scene.

2. Service downtime: the lock cannot be released due to service downtime, and then a deadlock occurs. Set the expiration time. After the service is restarted, the expired data will be automatically cleared

6. Implementation of distributed lock (core code)

Based on atomic design, you can use lua script statement to obtain the lock and don't forget to release the lock (code on Daniel erhu)

    private static final RedisScript<String> SCRIPT_LOCK = new DefaultRedisScript<>(
            //When the key does not exist, set a value and set the expiration time (px indicates milliseconds)
            "return redis.call('set',KEYS[1],ARGV[1],'NX','PX',ARGV[2])",String.class
    );
    private static final RedisScript<String> SCRIPT_UNLOCK = new DefaultRedisScript<>(
            //Judge whether this key returns' false ', delete it and return' true '
            "if redis.call('get',KEYS[1]) == ARGV[1] then return tostring(redis.call('del',KEYS[1]) == 1) else return 'false' end",String.class
    );
    private static final String LOCK_SUCCESS = "OK";

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public boolean acquireLock(String lockKey, String lockValue) {
        Object lockResult = redisTemplate.execute(SCRIPT_LOCK,
                redisTemplate.getStringSerializer(),
                redisTemplate.getStringSerializer(),
                Collections.singletonList(lockKey),
                lockValue);
        return LOCK_SUCCESS.equals(lockResult);
    }

    @Override
    public boolean releaseLock(String lockKey,String lockValue) {
        Object releaseResult = redisTemplate.execute(SCRIPT_UNLOCK,
                redisTemplate.getStringSerializer(),
                redisTemplate.getStringSerializer(),
                Collections.singletonList(lockKey),
                lockValue);
        return Boolean.valueOf(releaseResult.toString());
    }

If you don't understand this, press one button three times and hold me for private chat late at night (cough, the recent serious overtime must be arranged late at night)

Added by mrbaseball34 on Wed, 19 Jan 2022 19:01:39 +0200