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电商网站开发(服务端)的更多相关文章

  1. 【笔记3-用户模块】从0开始 独立完成企业级Java电商网站开发(服务端)

    数据表结构设计 关系设计 为什么不用外键? 分库分表有外键会非常麻烦,清洗数据也很麻烦.数据库内置触发器也不适合采用. 查业务问题的后悔药--时间戳 create_time 数据创建时间 update ...

  2. 【笔记7-部署发布】从0开始 独立完成企业级Java电商网站开发(服务端)

    阿里云服务 购买 连接 购买域名 域名备案 域名解析 源配置步骤 资源地址 http://learning.happymmall.com/ 配置阿里云的yum源 1.备份 mv /etc/yum.re ...

  3. 【笔记4-商品模块】从0开始 独立完成企业级Java电商网站开发(服务端)

    分类管理模块 数据表结构设计 分类表 CREATE TABLE.mmall_ category' ( 'id' int(11) NOT NULL AUTO_ INCREMENT COMMENT ' 类 ...

  4. 【笔记6-支付及订单模块】从0开始 独立完成企业级Java电商网站开发(服务端)

    支付模块 实际开发工作中经常会遇见如下场景,一个支付模块,一个订单模块,有一定依赖,一个同事负责支付模块,另一个同事负责订单模块,但是开发支付模块的时候要依赖订单模块的相关类 ,方法,或者工具类,这些 ...

  5. 【笔记5-购物车及地址模块】从0开始 独立完成企业级Java电商网站开发(服务端)

    购物车模块 数据库表设计 购物车表 CREATE TABLE mmall_ cart ( 'id' int(11) NOT NULL AUTO_ INCREMENT, 'user_ id' int(1 ...

  6. 【笔记2-环境配置及初始化】从0开始 独立完成企业级Java电商网站开发(服务端)

    准备工作 Linux系统安装 云服务器部署 概要 申请和配置 域名的购买.解析.配置.绑定流程 用户创建实操 环境安装及部署 JDK.Tomcat.Maven下载安装及配置 vsftpd下载安装及配置 ...

  7. 从0开始独立完成企业级Java电商网站开发(服务端)

    数据表结构设计 唯一索引unique,保证数据唯一性 CREATE TABLE `mmall_user` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT ...

  8. Redis 分布式锁进化史(解读 + 缺陷分析)

    Redis分布式锁进化史 近两年来微服务变得越来越热门,越来越多的应用部署在分布式环境中,在分布式环境中,数据一致性是一直以来需要关注并且去解决的问题,分布式锁也就成为了一种广泛使用的技术,常用的分布 ...

  9. 一文看透 Redis 分布式锁进化史(解读 + 缺陷分析)(转)

    近两年来微服务变得越来越热门,越来越多的应用部署在分布式环境中,在分布式环境中,数据一致性是一直以来需要关注并且去解决的问题,分布式锁也就成为了一种广泛使用的技术,常用的分布式实现方式为Redis,Z ...

随机推荐

  1. TCP/IP详解,卷1:协议--RARP:逆地址解析协议

    引言 具有本地磁盘的系统引导时,一般是从磁盘上的配置文件中读取 I P地址.但是无盘机, 如X终端或无盘工作站,则需要采用其他方法来获得 I P地址. 网络上的每个系统都具有唯一的硬件地址,它是由网络 ...

  2. 2019-08-01 纪中NOIP模拟B组

    T1 [JZOJ2642] 游戏 题目描述 Alice和Bob在玩一个游戏,游戏是在一个N*N的矩阵上进行的,每个格子上都有一个正整数.当轮到Alice/Bob时,他/她可以选择最后一列或最后一行,并 ...

  3. 2.7.5 元素定位(主推xpath、cssSelector) ❀❀❀

    定位方式选择: 1. 当页面元素有id属性时,最好尽量用id来定位.但由于现实项目中很多程序员其实写的代码并不规范,会缺少很多标准属性,这时就只有选择其他定位方法. 2. xpath很强悍,但定位性能 ...

  4. [C++] JsonCPP 的使用 完整配置过程

    最近准备开发一个程序 需要用到C++ 解析json 原始的C++解析json是不现实的 自己也写不出来json解析方法(主要是不靠谱) 所以找到了jsoncpp 这个库 但是... 因为各种原因 配置 ...

  5. 题解 【Codeforces387B】George and Round

    以下选自官方题解: 考虑困难的需求数量,我们将覆盖这些困难, 然后我们将提出新的问题,并准备新的问题来覆盖其他需求. 很明显,如果我们决定满足从n中抽取i的要求,那么最好采用那些复杂性最小的要求. 让 ...

  6. testng的prioriy

    todo: 同一个class中的priority: 1.不标priority的case和标注priority的case,谁先谁后? 2.标注相同priority的case,谁先谁后?是不是并发? 3. ...

  7. 【C语言】用C语言输出“心形”图案

    在你们的世界里,是不是觉得程序猿一点浪漫都不懂?其实不是的,程序猿的世界也是很浪漫滴! 傻瓜版 int main() { printf("❤"); ; } 高级版 //版本一:单个 ...

  8. Call to undefined function Illuminate\Encryption\openssl_cipher_iv_length()

    今天遇到一个错误,没有定义一个openssl_cipher_iv_length()方法,可是我明明开启OpenSSL了啊 如果开启了还报错 只需要把php的目录加入环境变量 -重启电脑  就解决了 但 ...

  9. 【转自】自定义InputFormat、OutputFormat

    转自:http://www.cnblogs.com/xiaolong1032/p/4529534.html 一:自定义实现InputFormat *数据源来自于内存*1.InputFormat是用于处 ...

  10. Python requests库模拟浏览器行为的一些技巧记录

    如下都是一些经验之谈,不定期更新,喜欢可以关注哦. 忽略ssl报错 一些证书问题会导致程序报错,解决方法为在发送请求的时候,带上verify=False参数即可: result = requests. ...