Redis分布式锁
Redis分布式锁命令
-
setnx当且仅当 key 不存在。若给定的 key 已经存在,则 setnx不做任何动作。setnx 是『set if not exists』(如果不存在,则 set)的简写,setnx 具有原子性。
-
getset先 get 旧值,后set 新值,并返回 key 的旧值(old value),具有原子性。当 key 存在但不是字符串类型时,返回一个错误;当key 不存在的时候,返回nil ,在Java里就是 null。
-
expire 设置 key 的有效期
-
del 删除 key
Redis分布式锁流程图
Redis分布式锁优化版流程图
Spring Schedule + Redis分布式锁,构建分布式任务调度
@Component
@Slf4j
public class CloseOrderTask {
private static final Loggerlog = LoggerFactory.getLogger(CloseOrderTask.class);
@Autowired
private IOrderServiceiOrderService;
@PreDestroy // 关闭Tomcat之前执行删除锁,避免死锁
public void delLock(){
RedisShardedPoolUtil.del(Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK);
}
// @Scheduled(cron = "0 */1 * * * ?")//每一分钟(每个一分钟的整数倍)
public void closeOrderTaskV1(){
int hour=Integer.parseInt(PropertiesUtil.getProperty("close.order.task.time.hour","2"));
log.info("关闭订单定时任务启动");
iOrderService.closeorder(hour);
log.info("关闭订单定时任务结束");
}
// @Scheduled(cron = "0 */1 * * * ?")//每一分钟(每个一分钟的整数倍)
public void closeOrderTaskV2(){
log.info("关闭订单定时任务启动");
// 锁超时时间
long lockTimeout=Long.parseLong(PropertiesUtil.getProperty("lock.timeout","5000"));
// 不存在则设置
Long setnxResult= RedisShardedPoolUtil.setnx(Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK,String.valueOf(System.currentTimeMillis()+lockTimeout));
if(setnxResult!=null&&setnxResult.intValue()==1){
//如果返回值是1,代表设置成功,获取锁
closeOrder(Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK);
}else{
log.info("没有获得分布式锁:{}",Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK);
}
log.info("关闭订单定时任务结束");
}
@Scheduled(cron ="0 */1 * * * ?")//每一分钟(每个一分钟的整数倍)
public void closeOrderTaskV3(){
log.info("关闭订单定时任务启动");
//锁超时时间
long lockTimeout=Long.parseLong(PropertiesUtil.getProperty("lock.timeout","5000"));
Long setnxResult= RedisShardedPoolUtil.setnx(Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK,String.valueOf(System.currentTimeMillis()+lockTimeout));
if(setnxResult!=null&&setnxResult.intValue()==1){
//如果返回值是1,代表设置成功,获取锁
closeOrder(Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK);
}else{
//未获取到锁,继续判断,判断时间戳,看是否可以重置并获取到锁
String lockValueStr=RedisShardedPoolUtil.get(Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK);
if(lockValueStr!=null&&System.currentTimeMillis()>Long.parseLong(lockValueStr)){
String getSetResult=RedisShardedPoolUtil.getSet(Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK,String.valueOf(System.currentTimeMillis()+lockTimeout));
//再次用当前时间戳getset
//返回给定的key的旧值,-》旧值判断,是否可以获取锁
//当key没有旧值时,即key不存在时,返回nil->获取锁
//这里我们set了一个新的value值,获取旧的值
if(getSetResult==null||(getSetResult!=null&& StringUtils.equals(lockValueStr,getSetResult))){
//真正获取到锁
closeOrder(Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK);
}else{
log.info("没有获取到分布式锁:{}",Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK);
}
}else{
log.info("没有获取到分布式锁:{}",Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK);
}
}
log.info("关闭订单定时任务结束");
}
private void closeOrder(String lockName){
RedisShardedPoolUtil.expire(lockName,50);//有效期5秒,防止死锁
log.info("获取{} ,ThreadName:{}",Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK,Thread.currentThread().getName());
int hour=Integer.parseInt(PropertiesUtil.getProperty("close.order.task.time.hour","2"));
// iOrderService.closeorder(hour);
RedisShardedPoolUtil.del(Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK);
log.info("释放{} ,ThreadName:{}",Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK,Thread.currentThread().getName());
log.info("============================");
}
}
Tomcat集群快速入门
Nginx负载均衡配置、常用策略、场景及特点
- 轮询(默认)
- 权重
- ip hash
- url hash(第三方)
- fail(第三方)
Nginx+Tomcat搭建集群
https://blog.csdn.net/Leon_Jinhai_Sun/article/details/97640796
Tomcat集群快速入门
https://blog.csdn.net/Leon_Jinhai_Sun/article/details/97624274
https://blog.csdn.net/Leon_Jinhai_Sun/article/details/97631761
参考: