Redisson的分布式锁的简单实现

Redisson的分布式锁的简单实现

更多请参考官网:
redisson的GitHub:https://github.com/redisson/redisson/wiki
环境:springboot2.2.5,mybatis,redis,
1.Maven依赖

     <dependency>
      <groupId>org.redisson</groupId>
      <artifactId>redisson</artifactId>
      <version>3.8.0</version>
    </dependency>

2.Yaml

server:
  port: 8099

spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/redis_demo?serverTimezone=GMT%2B8
    username: root
    password: 123456
    hikari: # https://github.com/brettwooldridge/HikariCP (uses milliseconds for all time values)
      maximumPoolSize: 10
      minimumIdle: 2
      idleTimeout: 600000
      connectionTimeout: 30000
      maxLifetime: 1800000
  # Redis数据库索引(默认为0)
  redis:
    database: 0
     # Redis服务器地址
    host: 192.168.221.136
    # Redis服务器连接端口
    port: 7000
    # Redis服务器连接密码(默认为空)
    password:
    # 连接池最大连接数(使用负值表示没有限制)
    jedis:
      pool:
        max-active: 200
          # 连接池最大阻塞等待时间(使用负值表示没有限制)
          #        max-wait: -1
          # 连接池中的最大空闲连接
        max-idle: 10
          # 连接池中的最小空闲连接
        min-idle: 0
      # 连接超时时间(毫秒)
    timeout: 10000

## 该配置节点为独立的节点,有很多同学容易将这个配置放在spring的节点下,导致配置无法被识别
mybatis:
  mapUnderscoreToCamelCase: true
  typeAliasesPackage: com.ls.pojo
  mapperLocations: classpath:mappers/*.xml

3.RedisSonConfig配置类

@Configuration
public class RedisSonConfig {

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

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

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

    @Bean
    public RedissonClient getRedisson() {
        Config config = new Config();
        config.useSingleServer().setAddress("redis://" + host + ":" + port);
        //config.useSingleServer().setAddress("redis://" + host + ":" + port).setPassword(password);
        //添加主从配置
        //config.useMasterSlaveServers().setMasterAddress("").setPassword("").addSlaveAddress(new String[]{"", ""});
        return Redisson.create(config);
    }


}

4.主要业务代码及实现

 @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean killItemV4(Long killId, Integer buyNum) throws Exception {
        Boolean result = false;
        String keyId = String.valueOf(killId);
        final String lockKey = new StringBuffer().append(killId).append("-RedisSonLock").toString();
        RLock lock = redisSonUtils.getRLock(lockKey);

        try {
            /**
             * 第一个参数30s=表示尝试获取分布式锁,并且最大的等待获取锁的时间为30s
             * 第二个参数10s=表示上锁之后,10s内操作完毕将自动释放锁
             */
            Boolean cacheRes = lock.tryLock(30, 10, TimeUnit.SECONDS);
            if (cacheRes) {
                //TODO:核心业务逻辑的处理
                //先从redis查库存
                stockNum = (Integer) redisUtil.get(keyId);
                logger.info("redis库存:" + stockNum);
                if (stockNum == null) {
                    TbItem dbTbItem = tbItemMapper.selectByPrimaryKey(killId);
                    stockNum = dbTbItem.getNum();
                    redisUtil.set(keyId, stockNum);
                }
                if (stockNum <= 0) {
                    throw new Exception("库存不足01!");
                }
                if (stockNum >= 0) {
                    //先更新redis库存
                    Long kcNum = redisUtil.decr(keyId, buyNum);
                    logger.info("redis剩余库存:" + kcNum);
                    stockNum -= buyNum;
                    if (kcNum.intValue() != stockNum) {
                        throw new Exception("系统错误!");
                    }
                    TbItem tbItem = new TbItem();
                    tbItem.setId(killId);
                    tbItem.setNum(stockNum);
                    tbItem.setUpdated(new Date());
                    //更新数据库库存
                    int res = tbItemMapper.updateByPrimaryKeySelective(tbItem);
                    if (res > 0 && stockNum >= 0) {
                        logger.info("购买成功");
                        result = true;
                    }
                }
            }

        } finally {
            //TODO:释放锁
            lock.unlock();
        }
        return result;

    }

5.测试结果
redis:
在这里插入图片描述
在这里插入图片描述
开20线程,使用JMeter测试
在这里插入图片描述
成功5个,失败15
在这里插入图片描述
redis库存
在这里插入图片描述
数据库库存
在这里插入图片描述
6.更多代码请访问我的github:https://github.com/smileLs66/springboot
项目名是:redisson
若发现错误还请各位大佬指正;谢谢
欢迎兴趣的同学一起交流:qq群:1081601635

posted @ 2020-03-13 14:14  smileLS66  阅读(64)  评论(0编辑  收藏  举报