【笔记8-Redis分布式锁】从0开始 独立完成企业级Java电商网站开发(服务端)
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
参考:
https://www.jianshu.com/p/ca88c1f86069
https://blog.csdn.net/qq_20057315/article/details/81624821
【笔记8-Redis分布式锁】从0开始 独立完成企业级Java电商网站开发(服务端)的更多相关文章
- 【笔记3-用户模块】从0开始 独立完成企业级Java电商网站开发(服务端)
数据表结构设计 关系设计 为什么不用外键? 分库分表有外键会非常麻烦,清洗数据也很麻烦.数据库内置触发器也不适合采用. 查业务问题的后悔药--时间戳 create_time 数据创建时间 update ...
- 【笔记7-部署发布】从0开始 独立完成企业级Java电商网站开发(服务端)
阿里云服务 购买 连接 购买域名 域名备案 域名解析 源配置步骤 资源地址 http://learning.happymmall.com/ 配置阿里云的yum源 1.备份 mv /etc/yum.re ...
- 【笔记4-商品模块】从0开始 独立完成企业级Java电商网站开发(服务端)
分类管理模块 数据表结构设计 分类表 CREATE TABLE.mmall_ category' ( 'id' int(11) NOT NULL AUTO_ INCREMENT COMMENT ' 类 ...
- 【笔记6-支付及订单模块】从0开始 独立完成企业级Java电商网站开发(服务端)
支付模块 实际开发工作中经常会遇见如下场景,一个支付模块,一个订单模块,有一定依赖,一个同事负责支付模块,另一个同事负责订单模块,但是开发支付模块的时候要依赖订单模块的相关类 ,方法,或者工具类,这些 ...
- 【笔记5-购物车及地址模块】从0开始 独立完成企业级Java电商网站开发(服务端)
购物车模块 数据库表设计 购物车表 CREATE TABLE mmall_ cart ( 'id' int(11) NOT NULL AUTO_ INCREMENT, 'user_ id' int(1 ...
- 【笔记2-环境配置及初始化】从0开始 独立完成企业级Java电商网站开发(服务端)
准备工作 Linux系统安装 云服务器部署 概要 申请和配置 域名的购买.解析.配置.绑定流程 用户创建实操 环境安装及部署 JDK.Tomcat.Maven下载安装及配置 vsftpd下载安装及配置 ...
- 从0开始独立完成企业级Java电商网站开发(服务端)
数据表结构设计 唯一索引unique,保证数据唯一性 CREATE TABLE `mmall_user` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT ...
- Redis 分布式锁进化史(解读 + 缺陷分析)
Redis分布式锁进化史 近两年来微服务变得越来越热门,越来越多的应用部署在分布式环境中,在分布式环境中,数据一致性是一直以来需要关注并且去解决的问题,分布式锁也就成为了一种广泛使用的技术,常用的分布 ...
- 一文看透 Redis 分布式锁进化史(解读 + 缺陷分析)(转)
近两年来微服务变得越来越热门,越来越多的应用部署在分布式环境中,在分布式环境中,数据一致性是一直以来需要关注并且去解决的问题,分布式锁也就成为了一种广泛使用的技术,常用的分布式实现方式为Redis,Z ...
随机推荐
- echart如何去掉X 、Y轴的网格线
1.如何去掉X.Y轴的网格线,关键是splitLine{show:false} xAxis:[{ type:'value', splitNumber:2, scale:true, splitLine: ...
- 圆桌问题 (ArrayList+模拟)
圆桌上围坐着2n个人.其中n个人是好人,另外n个人是坏人.如果从第一个人开始数数,数到第m个人,则立即处死该人:然后从被处死的人之后开始数数,再将数到的第m个人处死……依此方法不断处死围坐在圆桌上的人 ...
- blur()低通滤波
blur()函数可以用标准化的盒式过滤器来平滑图像. C++ API: 相关官网资料: https://docs.opencv.org/3.4.1/d4/d86/group__imgproc__fil ...
- input输入框在ios手机上获取焦点后有一个灰色阴影
遇到的场景: 有一个输入框 设置 outline:none 然后我又想给他设置获取焦点的颜色 然后 我给input 设置 border 为 1px t透明的 然后 获取焦点的时候 重新设置border ...
- AcWing 873. 欧拉函数
//用定义直接求 #include<bits/stdc++.h> using namespace std; int main() { int n; cin>>n; while( ...
- 每天进步一点点------Allegro生成Gerber文件
Allegro如何生成光绘文件 -------------------制板用文件有钻孔文件和底片文件,最后给板厂的文件为:---------------------------普通二层板:nc_par ...
- Vue - 表单修饰符
.lazy 在默认情况下,v-model 在每次 input 事件触发后将输入框的值与数据进行同步 . 使用 lazy 修饰符,从而转变为使用 change 事件进行同步 <div id=&qu ...
- 移动端 输入框 input 被弹出来的键盘 挡住
给被挡住的input或者textarea加一个id,然后在click事件里调用下面的代码 document.querySelector('#xxx').scrollIntoView();
- redis哈希操作
用户可以通过执行hset命令为哈希中的指定字段设置值: 127.0.0.1:6379> hset hash field value 根据给定的字段是否存在于散列中,hset命令的行为也会有所不同 ...
- python+pygame的导弹追踪鼠标游戏设置和说明
1.效果图 2.注意事项,代码里有说明 3.完整的代码 #导出模块 import pygame,sys from math import * #设置RESIZABLE前,必须导出下面的模块,否则报错 ...