赞
踩
秒杀抢购业务
redis中初始库存数量10,订单数量0
每抢购一单,库存数量-1,订单数量+1
不加锁会出现超卖现象
程序代码加锁可以防止。但如果有多个客户端分布式部署,加锁仍然会出现超卖。因为锁是依赖于当前程序的进程,启动多个进程实际上是多把锁。可以通过在redis加分布式锁,来实现在多个进程中来维护同一个锁对象redis是全局单线程的,可以保证同一时间只有一个客户端持有锁。没有抢到锁立即返回结果。
SETNX lockName value
如果键不存在,则设置成功,返回true,也就是抢到锁。如果键已经存在,则返回false,说明其他客户端在占有锁
PEXPIRE lockName 1500
为键设置过期时间防止某一客户端得到锁突然宕掉,没来得及释放锁,后面其他客户端就不能得到锁
Boolean lock = redisTemplate.opsForValue().setIfAbsent(lockkName, value, 30, TimeUnit.SECONDS);
if(lock) {
//加锁成功...
// todo business
redisTemplate.delete(lockName); //删除key,释放锁
} else {
// 加锁失败
return false
}
1.客户端拿到锁,程序执行异常没有释放锁,导致其他客户端无法拿到锁
解决方式:为锁设置过期时间。到达过期时间后锁自动释放
2.设置锁与设置过期时间不是原子性的。可能出现获取到锁但还没设置过期时间客户端就宕机了。
解决方式:在设置锁的同事设置过期时间
redisTemplate.opsForValue().setIfAbsent(lockkName, value, 30, TimeUnit.SECONDS);
MULTI 命令标志着事务的开始
会将redis命令按次序放入一个事务队列中,先不执行
EXEC 执行事务,依次执行事务队列中的命令,将结果一起返回给客户端
DISCARD 取消事务
WATCH 命令在EXEC命令执行之前监视一个键。在EXEC命令执行时,如果被监视的键被更改,服务器就会拒绝执行事务,向客户端返回执行失败的空回复。
try{
jedis.watch("age");
// 开启事务
Transaction transaction = jedis.multi();
transaction.set("key-1", "value-1");
transaction.set("key-2", "value-2");
transaction.set("key-3", "value-3");
transaction.set("key-4", "value-4");
// 提交事务 //放弃事务
transaction.exec();//transaction.discard();
}catch(Exception e){
}
要么全部执行,要么全部失败。exec执行后,取消对所有键的监视
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。