阅读量:0
使用redis的setnx命令放入数据并用此数据当锁完成业务(但是如果用户操作途中出现异常导致超出指定时间会出现问题)
@Service public class StockService { @Autowired private StockDao stockDao; //mapper注入 @Autowired private StringRedisTemplate redisTemplate; //使用redis方法 // public String decrement(Integer productid) { ValueOperations<String, String> opsForValue = redisTemplate.opsForValue(); //1.获取共享锁资源(通过进行redis放入数据的方式,如果放入成功说明redis没有该数据) Boolean flag = opsForValue.setIfAbsent("product::" + productid, "1111", 30, TimeUnit.SECONDS); //表示获取锁成功 if(flag) { try { //根据id查询商品的库存 int num = stockDao.findById(productid); if (num > 0) { //修改库存 stockDao.update(productid); System.out.println("商品编号为:" + productid + "的商品库存剩余:" + (num - 1) + "个"); return "商品编号为:" + productid + "的商品库存剩余:" + (num - 1) + "个"; } else { System.out.println("商品编号为:" + productid + "的商品库存不足。"); return "商品编号为:" + productid + "的商品库存不足。"; } }finally { //释放锁资源(删除放入的该数据,然后准备开始下一次抢锁) redisTemplate.delete("product::"+productid); } }else{ //休眠100毫秒 在继续抢锁 try { Thread.sleep(100); } catch (InterruptedException e) { throw new RuntimeException(e); } return decrement(productid); } } }
看门狗(改善版,解决了超时的bug)
引入依赖
<dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.24.3</version> </dependency>
编写配置类
@Configuration public class RedissonConfig { @Bean public RedissonClient redisson(){ Config config = new Config(); //连接redis集群 config.useClusterServers() use "rediss://" for SSL connection .addNodeAddress("redis://127.0.0.1:7181","","",""); //连接单机 config.useSingleServer().setAddress("redis://192.168.111.188:6379"); RedissonClient redisson = Redisson.create(config); return redisson; } }
业务代码
@Service public class StockService { @Autowired private StockDao stockDao; //注入mapper @Autowired private RedissonClient redisson; //注入看门狗 // public String decrement(Integer productid) { RLock lock = redisson.getLock("product::" + productid); //获取锁资源 lock.lock(); //上锁 try { //根据id查询商品的库存: 提前预热到redis缓存中 int num = stockDao.findById(productid); if (num > 0) { //修改库存---incr---定时器[redis 数据库同步] stockDao.update(productid); System.out.println("商品编号为:" + productid + "的商品库存剩余:" + (num - 1) + "个"); return "商品编号为:" + productid + "的商品库存剩余:" + (num - 1) + "个"; } else { System.out.println("商品编号为:" + productid + "的商品库存不足。"); return "商品编号为:" + productid + "的商品库存不足。"; } }finally { lock.unlock(); //释放锁资源 } } }