解决redis多客户端并发竞争key:采用Redisson客户端加锁

业务场景:

多个客户端并发竞争key,实现操作,保证所有客户端实现串行对key操作成功

设计思路:

采用Redisson客户端实现分布式锁,保证并发操作命令串行化执行,预期结果准确

事例:

   设计demo1,demo2,同事有如下代码相当于6个线程并发对anyLock中值进行修改,串行执行,预期结果是330

   并发执行demo1 接口:http://127.0.0.1:9999/redissonOpt/makeRedisLockKeyParallel,demo2接口:http://127.0.0.1:9000/redissonOpt/makeRedisLockKeyParallel

package com.szk.app;

import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
/**
 * @ProjectName: szk_demo
 * @Package: com.szk.app
 * @ClassName: RedissonOpt
 * @Author: pc
 * @Description:
 * @Date: 2021/4/29 15:21
 */

@RestController
@RequestMapping("redissonOpt")
public class RedissonOpt {
    @Autowired
    Redisson  redisson;
    @Autowired
    RedisTemplate redisTemplate;

    /**
     * @Method
     * @Author pc
     * @Version  1.0
     * @Description  单独测试
     * @Param
     * @Return
     * @Exception
     * @Date 2021/5/11
     */
    @RequestMapping(value="makeRedisLockKey",method = RequestMethod.POST)
    public  void makeRedisLockKey(String key){
        System.out.println("");
        RLock lock = redisson.getLock("anyLock");
        lock.lock();
        //
        boolean flag = lock.isLocked();
        if(flag){
            redisTemplate.opsForValue().set("anyLock",0);
        }
        System.out.println(flag);

        lock.unlock();
    }
    /**
     * @Method
     * @Author pc
     * @Version  1.0
     * @Description  多线程测试,实现对求和功能
     * @Param
     * @Return
     * @Exception
     * @Date 2021/5/11
     */
    @RequestMapping(value="makeRedisLockKeyParallel",method = RequestMethod.POST)
    public  void makeRedisLockKeyParallel(String key){
        Thread thread1=   new Thread(new Runnable() {

            @Override
            public void run() {
                toValue();
            }
        });
        thread1.setName("004");
        thread1.start();

        Thread thread2=new Thread(new Runnable() {

            @Override
            public void run() {
                toValue();
            }
        });
        thread2.setName("005");
        thread2.start();

        Thread thread3=new Thread(new Runnable(){
            @Override
            public void run() {
                toValue();
            }
        });
        thread3.setName("006");
        thread3.start();
    }

    /**
     * @Method
     * @Author pc
     * @Version  1.0
     * @Description  实现求和
     * @Param
     * @Return
     * @Exception
     * @Date 2021/5/11
     */
    private void toValue() {
        for (int i = 0; i <= 10; i++) {

            String ss="当前线程是demo2 " +Thread.currentThread().getName();
            System.out.println(ss+" 开始执行。。。。");
            RLock lock = redisson.getLock("anyLock");
            boolean flag=lock.isLocked();
            System.out.println(ss+"检查"+System.currentTimeMillis()+"此时isLocked: "+flag);
            lock.lock();
            System.out.println(ss+" 获取锁成功");
            int count= 0;
            try {
                count = Integer.valueOf(redisTemplate.opsForValue().get("anyLock").toString());
            } catch (NumberFormatException e) {
                e.printStackTrace();
            }finally {
                redisTemplate.opsForValue().set("anyLock",i);
            }

            count=count+i;
            redisTemplate.opsForValue().set("anyLock", count);


            System.out.println(ss+"执行结果:"+redisTemplate.opsForValue().get("anyLock"));

            lock.unlock();

        }
    }

}

执行结果:

demo1 执行console:

当前线程是demo1 001 开始执行。。。。
当前线程是demo1 002 开始执行。。。。
当前线程是demo1 003 开始执行。。。。
当前线程是demo1 001检查1620701188596此时isLocked: false
当前线程是demo1 002检查1620701188598此时isLocked: false
当前线程是demo1 003检查1620701188599此时isLocked: false
当前线程是demo1 001 获取锁成功
当前线程是demo1 001执行结果:0
当前线程是demo1 001 开始执行。。。。
当前线程是demo1 002 获取锁成功
当前线程是demo1 001检查1620701188797此时isLocked: false
当前线程是demo1 002执行结果:0
当前线程是demo1 002 开始执行。。。。
当前线程是demo1 003 获取锁成功
当前线程是demo1 002检查1620701188953此时isLocked: true
当前线程是demo1 003执行结果:0
当前线程是demo1 003 开始执行。。。。
当前线程是demo1 003检查1620701189111此时isLocked: true
当前线程是demo1 001 获取锁成功
当前线程是demo1 001执行结果:1
当前线程是demo1 001 开始执行。。。。
当前线程是demo1 001检查1620701189258此时isLocked: false
当前线程是demo1 002 获取锁成功
当前线程是demo1 002执行结果:2
当前线程是demo1 002 开始执行。。。。
当前线程是demo1 002检查1620701189409此时isLocked: false
当前线程是demo1 003 获取锁成功
当前线程是demo1 003执行结果:3
当前线程是demo1 003 开始执行。。。。
当前线程是demo1 003检查1620701189556此时isLocked: false
当前线程是demo1 001 获取锁成功
当前线程是demo1 001执行结果:5
当前线程是demo1 001 开始执行。。。。
当前线程是demo1 001检查1620701189707此时isLocked: false
当前线程是demo1 002 获取锁成功
当前线程是demo1 002执行结果:7
当前线程是demo1 002 开始执行。。。。
当前线程是demo1 002检查1620701189862此时isLocked: true
当前线程是demo1 003 获取锁成功
当前线程是demo1 003执行结果:9
当前线程是demo1 003 开始执行。。。。
当前线程是demo1 003检查1620701190010此时isLocked: false
当前线程是demo1 001 获取锁成功
当前线程是demo1 001执行结果:27
当前线程是demo1 001 开始执行。。。。
当前线程是demo1 001检查1620701191973此时isLocked: true
当前线程是demo1 002 获取锁成功
当前线程是demo1 002执行结果:34
当前线程是demo1 002 开始执行。。。。
当前线程是demo1 002检查1620701192288此时isLocked: true
当前线程是demo1 003 获取锁成功
当前线程是demo1 003执行结果:173
当前线程是demo1 003 开始执行。。。。
当前线程是demo1 003检查1620701195277此时isLocked: false
当前线程是demo1 002 获取锁成功
当前线程是demo1 002执行结果:177
当前线程是demo1 002 开始执行。。。。
当前线程是demo1 002检查1620701195432此时isLocked: false
当前线程是demo1 003 获取锁成功
当前线程是demo1 003执行结果:191
当前线程是demo1 003 开始执行。。。。
当前线程是demo1 001 获取锁成功
当前线程是demo1 003检查1620701195743此时isLocked: true
当前线程是demo1 001执行结果:195
当前线程是demo1 001 开始执行。。。。
当前线程是demo1 001检查1620701195904此时isLocked: true
当前线程是demo1 002 获取锁成功
当前线程是demo1 002执行结果:200
当前线程是demo1 003 获取锁成功
当前线程是demo1 003执行结果:205
当前线程是demo1 003 开始执行。。。。
当前线程是demo1 003检查1620701196221此时isLocked: false
当前线程是demo1 001 获取锁成功
当前线程是demo1 002 开始执行。。。。
当前线程是demo1 002检查1620701196310此时isLocked: true
当前线程是demo1 001执行结果:210
当前线程是demo1 001 开始执行。。。。
当前线程是demo1 001检查1620701196381此时isLocked: true
当前线程是demo1 003 获取锁成功
当前线程是demo1 003执行结果:216
当前线程是demo1 003 开始执行。。。。
当前线程是demo1 002 获取锁成功
当前线程是demo1 003检查1620701196539此时isLocked: false
当前线程是demo1 002执行结果:222
当前线程是demo1 002 开始执行。。。。
当前线程是demo1 001 获取锁成功
当前线程是demo1 002检查1620701196694此时isLocked: true
当前线程是demo1 001执行结果:228
当前线程是demo1 001 开始执行。。。。
当前线程是demo1 003 获取锁成功
当前线程是demo1 001检查1620701196843此时isLocked: false
当前线程是demo1 003执行结果:235
当前线程是demo1 003 开始执行。。。。
当前线程是demo1 003检查1620701196990此时isLocked: true
当前线程是demo1 002 获取锁成功
当前线程是demo1 002执行结果:242
当前线程是demo1 002 开始执行。。。。
当前线程是demo1 001 获取锁成功
当前线程是demo1 002检查1620701197138此时isLocked: false
当前线程是demo1 001执行结果:249
当前线程是demo1 001 开始执行。。。。
当前线程是demo1 003 获取锁成功
当前线程是demo1 003执行结果:257
当前线程是demo1 003 开始执行。。。。
当前线程是demo1 001检查1620701197568此时isLocked: true
当前线程是demo1 003检查1620701197588此时isLocked: false
当前线程是demo1 002 获取锁成功
当前线程是demo1 002执行结果:265
当前线程是demo1 002 开始执行。。。。
当前线程是demo1 002检查1620701197735此时isLocked: false
当前线程是demo1 001 获取锁成功
当前线程是demo1 001执行结果:273
当前线程是demo1 001 开始执行。。。。
当前线程是demo1 001检查1620701197884此时isLocked: false
当前线程是demo1 003 获取锁成功
当前线程是demo1 003执行结果:282
当前线程是demo1 003 开始执行。。。。
当前线程是demo1 003检查1620701198034此时isLocked: false
当前线程是demo1 002 获取锁成功
当前线程是demo1 002执行结果:291
当前线程是demo1 002 开始执行。。。。
当前线程是demo1 002检查1620701198185此时isLocked: false
当前线程是demo1 001 获取锁成功
当前线程是demo1 001执行结果:300
当前线程是demo1 001 开始执行。。。。
当前线程是demo1 003 获取锁成功
当前线程是demo1 001检查1620701198340此时isLocked: true
当前线程是demo1 003执行结果:310
当前线程是demo1 002 获取锁成功
当前线程是demo1 002执行结果:320
当前线程是demo1 001 获取锁成功
当前线程是demo1 001执行结果:330

demo2 执行cosole:

当前线程是demo2 004 开始执行。。。。
当前线程是demo2 005 开始执行。。。。
当前线程是demo2 006 开始执行。。。。
当前线程是demo2 005检查1620701189641此时isLocked: true
当前线程是demo2 004检查1620701189643此时isLocked: true
当前线程是demo2 006检查1620701189644此时isLocked: true
当前线程是demo2 004 获取锁成功
当前线程是demo2 004执行结果:9
当前线程是demo2 004 开始执行。。。。
当前线程是demo2 006 获取锁成功
当前线程是demo2 004检查1620701190347此时isLocked: true
当前线程是demo2 006执行结果:9
当前线程是demo2 006 开始执行。。。。
当前线程是demo2 005 获取锁成功
当前线程是demo2 006检查1620701190490此时isLocked: true
当前线程是demo2 005执行结果:9
当前线程是demo2 005 开始执行。。。。
当前线程是demo2 004 获取锁成功
当前线程是demo2 005检查1620701190638此时isLocked: false
当前线程是demo2 004执行结果:10
当前线程是demo2 004 开始执行。。。。
当前线程是demo2 006 获取锁成功
当前线程是demo2 004检查1620701190781此时isLocked: true
当前线程是demo2 006执行结果:11
当前线程是demo2 006 开始执行。。。。
当前线程是demo2 005 获取锁成功
当前线程是demo2 006检查1620701190922此时isLocked: true
当前线程是demo2 005执行结果:12
当前线程是demo2 005 开始执行。。。。
当前线程是demo2 004 获取锁成功
当前线程是demo2 005检查1620701191064此时isLocked: true
当前线程是demo2 004执行结果:14
当前线程是demo2 004 开始执行。。。。
当前线程是demo2 006 获取锁成功
当前线程是demo2 004检查1620701191213此时isLocked: true
当前线程是demo2 006执行结果:16
当前线程是demo2 006 开始执行。。。。
当前线程是demo2 005 获取锁成功
当前线程是demo2 006检查1620701191361此时isLocked: false
当前线程是demo2 005执行结果:18
当前线程是demo2 005 开始执行。。。。
当前线程是demo2 005检查1620701191498此时isLocked: false
当前线程是demo2 004 获取锁成功
当前线程是demo2 004执行结果:21
当前线程是demo2 004 开始执行。。。。
当前线程是demo2 006 获取锁成功
当前线程是demo2 004检查1620701191648此时isLocked: true
当前线程是demo2 006执行结果:24
当前线程是demo2 006 开始执行。。。。
当前线程是demo2 006检查1620701191797此时isLocked: false
当前线程是demo2 004 获取锁成功
当前线程是demo2 004执行结果:31
当前线程是demo2 004 开始执行。。。。
当前线程是demo2 004检查1620701192131此时isLocked: true
当前线程是demo2 006 获取锁成功
当前线程是demo2 006执行结果:38
当前线程是demo2 006 开始执行。。。。
当前线程是demo2 006检查1620701192429此时isLocked: true
当前线程是demo2 005 获取锁成功
当前线程是demo2 005执行结果:41
当前线程是demo2 005 开始执行。。。。
当前线程是demo2 004 获取锁成功
当前线程是demo2 005检查1620701192578此时isLocked: true
当前线程是demo2 004执行结果:46
当前线程是demo2 004 开始执行。。。。
当前线程是demo2 006 获取锁成功
当前线程是demo2 004检查1620701192721此时isLocked: true
当前线程是demo2 006执行结果:51
当前线程是demo2 006 开始执行。。。。
当前线程是demo2 006检查1620701192859此时isLocked: true
当前线程是demo2 005 获取锁成功
当前线程是demo2 005执行结果:55
当前线程是demo2 005 开始执行。。。。
当前线程是demo2 004 获取锁成功
当前线程是demo2 005检查1620701192999此时isLocked: true
当前线程是demo2 004执行结果:61
当前线程是demo2 004 开始执行。。。。
当前线程是demo2 006 获取锁成功
当前线程是demo2 004检查1620701193142此时isLocked: false
当前线程是demo2 006执行结果:67
当前线程是demo2 006 开始执行。。。。
当前线程是demo2 005 获取锁成功
当前线程是demo2 006检查1620701193281此时isLocked: true
当前线程是demo2 005执行结果:72
当前线程是demo2 005 开始执行。。。。
当前线程是demo2 004 获取锁成功
当前线程是demo2 005检查1620701193424此时isLocked: true
当前线程是demo2 004执行结果:79
当前线程是demo2 004 开始执行。。。。
当前线程是demo2 006 获取锁成功
当前线程是demo2 004检查1620701193563此时isLocked: true
当前线程是demo2 006执行结果:86
当前线程是demo2 006 开始执行。。。。
当前线程是demo2 006检查1620701193700此时isLocked: false
当前线程是demo2 005 获取锁成功
当前线程是demo2 005执行结果:92
当前线程是demo2 005 开始执行。。。。
当前线程是demo2 005检查1620701193846此时isLocked: false
当前线程是demo2 004 获取锁成功
当前线程是demo2 004执行结果:100
当前线程是demo2 004 开始执行。。。。
当前线程是demo2 006 获取锁成功
当前线程是demo2 004检查1620701193990此时isLocked: true
当前线程是demo2 006执行结果:108
当前线程是demo2 006 开始执行。。。。
当前线程是demo2 006检查1620701194129此时isLocked: true
当前线程是demo2 005 获取锁成功
当前线程是demo2 005执行结果:115
当前线程是demo2 005 开始执行。。。。
当前线程是demo2 005检查1620701194271此时isLocked: true
当前线程是demo2 004 获取锁成功
当前线程是demo2 004执行结果:124
当前线程是demo2 004 开始执行。。。。
当前线程是demo2 006 获取锁成功
当前线程是demo2 004检查1620701194416此时isLocked: false
当前线程是demo2 006执行结果:133
当前线程是demo2 006 开始执行。。。。
当前线程是demo2 005 获取锁成功
当前线程是demo2 006检查1620701194562此时isLocked: true
当前线程是demo2 005执行结果:141
当前线程是demo2 005 开始执行。。。。
当前线程是demo2 005检查1620701194702此时isLocked: false
当前线程是demo2 004 获取锁成功
当前线程是demo2 004执行结果:151
当前线程是demo2 006 获取锁成功
当前线程是demo2 006执行结果:161
当前线程是demo2 005 获取锁成功
当前线程是demo2 005执行结果:170
当前线程是demo2 005 开始执行。。。。
当前线程是demo2 005检查1620701195132此时isLocked: true
当前线程是demo2 005 获取锁成功
当前线程是demo2 005执行结果:187

 预期验证分析:

   以上不难发现整个最终结果是330 符合我们预期

 

上一篇:Demo2 将一个字符由小写字母转换为大写字母


下一篇:effective解读-第九条 try-with-resource代替try-fanilly释放资源