java分布式锁分布式锁

java分布式&锁&分布式锁

  1. 锁的作用:有限资源的情况下,控制同一时间段,只有某些线程(用户/服务器)能访问到资源。
    在这里插入图片描述
  2. 锁在java中的实现:
    • synchronized关键字
    • 并发包的类
  3. 缺点:只对单个的jvm有效
    在这里插入图片描述

分布式锁

  1. 为什么实现分布式锁
    • 有限资源的情况下,控制同一段时间只有某些用户/服务器才能访问到资源
    • 单个锁只对单个jvm有效
  2. 分布锁实现(核心思想,先来server把数据改成自己的标识,后来的人发现标识已经存在就等待)
    • 抢锁机制 ==> 同一时间只有一个服务器能抢到资源 ==>
      1. Mysql数据库实现,数据库中有一个字段标识锁,哪个服务器先到达数据库,就将此标识改为自己服务器的值,下一个服务器查到达查看不为空就等待,知道此上一个服务器用完,将标识位改为空时,方可用。
        • 查select(控制只有一个服务器在查)(1.select for update 行级锁,2.乐观锁)
        • 改update
      2. redis实现,存标识。读写速度快,支持setnx,lua脚本实现
        • 原理:使用redis的setnx方法保证原子性质
          setnx:set if not exist如果不存在,则设置,只有设置成功才会返回true,否则返回false
          在这里插入图片描述
        • 注意1: 用完锁之后要释放,防止在释放之前服务器出现意外,因此要设置过期时间
        • 注意2:如果方法执行时间过长,锁提前过期,出现多个服务器同时执行。=> 续期(redisson中提供续期机制,原理:监听当前线程,默认过期时间是30s,每10s续期一次(补充到30s),如果线程挂了,则不会续期,如果debug模式也会被当成服务器宕机)。
        • 注意3:连锁效应:释放了其他server的锁 .=> 判断如果不是我的锁就不释放
        • 注意4:释放锁的时候,有可能先判断出是自己的锁,但是这时候锁过期了,会释放其他服务器/用户的锁 => 判断和释放的时候不允许其他任何的方法进入,redis原子性操作。配合redis+lua脚本。
    1. Zookeeper实现

控制定时任务的执行(在同一时间只有一个服务器能执行)

  1. 原因:

    • 浪费资源,假设有1000台服务器同时工作
    • 脏数据
      在这里插入图片描述
  2. 实现方式

    1. 分离定时任务,把控制定时任务从主程序中拆开(成本太大)
      在这里插入图片描述

    2. 配置,写死配置,每个服务器都执行定时任务,但是只有ip符合配置的才真实执行业务逻辑,其他的直接返回。
      在这里插入图片描述

    3. ☆动态配置,这个配置是可以轻松的跟新的,把配置写到数据库,Redis,配置中心(Nacos,Apollo,spring Cloud config)(问题:如果服务器数据太多,ip不可控制)
      在这里插入图片描述

    4. 分布式锁【只有抢到锁的服务器才能执行定时任务】

      在这里插入图片描述

Reddisson实现分布式锁

  1. Redisson:是一个java操作Redis的客户端,提供了大量的分布式数据集来简化对Redis的操作和使用,可以让开发者像使用本地集合一样使用Redis,完全感觉不到Redis的存在。
    redisson官网:redisson
  2. Redisson使用方法
    1. 支持springboot整合Rdisson,写配置,默认整合客户端。(版本迭代太快)
    2. 只引入Redisson,自己创建客户端
      1. 引入项目依赖Redisson类库
         <!--https://github.com/redisson/redisson#quick-start-->
                <dependency>
                    <groupId>org.redisson</groupId>
                    <artifactId>redisson</artifactId>
                    <version>3.21.3</version>
                </dependency>
        
      2. 新建redisson客户端
        /**
         * redisson配置
         */
        @Configuration
        @ConfigurationProperties(prefix = "spring.redis")
        @Data
        public class RedissonConfig {
            private String host;
            private String port;
        
            @Bean
            public RedissonClient redissonClient(){
                // 1. 创建配置对象
                Config config = new Config();
                String redisAddress = String.format("redis://%s:%s",host,port);
                config.useSingleServer().setAddress(redisAddress).setDatabase(3);
                // 2. 创建实例
                RedissonClient redisson = Redisson.create(config);
                return redisson;
            }
        }
        
      3. 使用锁实现缓存预热
        waitTime = 0 只抢一次
        /**
         * 缓存预热任务
         */
        @Slf4j
        public class PreCacheJob {
        
            @Resource
            private RedisTemplate<String, Object> redisTemplate;
            @Resource
            private UserService userService;
        
            @Resource
            public UserMapper userMapper;
        
            //重点用户
            private List<Long> mainUserList = Arrays.asList(1L);
            //引入redisson客户端
            @Resource
            private RedissonClient redissonClient;
        
            //每天执行,预热推荐用户
            @Scheduled(cron = "0 31 19 * * ? ")
            public void doCacheRecommendUser() {
                RLock lock = redissonClient.getLock("yupao:precachejob:docache:lock");
                try {
                    //waitTime:其他线程等待的时间,因为我们缓存预热每天只做一次,所以只要有一个线程拿到锁就
                    //leaseTime:锁过期时间
                    if (lock.tryLock(0, 30000L, TimeUnit.MILLISECONDS)) {//是否拿到锁
                        for (Long userId : mainUserList) {
                            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
                            Page<User> userPage = userService.page(new Page<>(1, 20),
                                    queryWrapper);
                            String redisKey = String.format("yupao:user:recommend:%s", userId);
                            ValueOperations<String, Object> valueOperations =
                                    redisTemplate.opsForValue();
                            //写缓存
                            try {
                                valueOperations.set(redisKey, userPage, 30000,
                                        TimeUnit.MILLISECONDS);
                            } catch (Exception e) {
                                log.error("redis set key error", e);
                            }
                        }
                    }
                } catch (InterruptedException e) {
                    log.error("doCacheRecommendUser error",e);
                } finally {
                    //释放自己的锁
                    if (lock.isHeldByCurrentThread()) {//是否是当前线程
                        System.out.println("unlock: " + Thread.currentThread().getId());
                        lock.unlock();
                    }
                }
            }
        }
        
        

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/194003.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

HCIA-H12-811题目解析(2)

1、【单选题】 在以太网这种多点访问网络上PPPOE服务器可以通过一个以太网端口与很多PPPOE客户端建立起PPP连接&#xff0c;因此服务器必须为每个PPP会话建立唯一的会话标识符以区分不同的连接PPPOE会使用什么参数建立会话标识符? 2、【单选题】PPP协议定义的是OSI参考模型中…

Chem. Eng. J | 掌控基于ESIPT的AIE效应设计具有单组分白光发射的光学材料

今天为大家介绍一篇近期发表在Chemical Engineering Journal上的论文&#xff1a;Controlling ESIPT-based AIE effects for designing optical materials with single-component white-light emission。论文通讯作者为中南大学董界副教授和曾文彬教授&#xff0c;论文第一作者…

【Leetcode】907. 子数组的最小值之和

给定一个整数数组 arr&#xff0c;找到 min(b) 的总和&#xff0c;其中 b 的范围为 arr 的每个&#xff08;连续&#xff09;子数组。 由于答案可能很大&#xff0c;因此 返回答案模 10^9 7 。 示例 1&#xff1a; 输入&#xff1a;arr [3,1,2,4] 输出&#xff1a;17 解释&…

1、Linux_介绍和安装

1. Linux概述 Linux&#xff1a;是基于Unix的一个开源、免费的操作系统&#xff0c;其稳定性、安全性、处理多并发能力强&#xff0c;目前大多数企业级应用甚至是集群项目都部署运行在linux操作系统之上&#xff0c;在我国软件公司得到广泛的使用 Unix&#xff1a;是一个强大…

RK3568平台开发系列讲解(Linux系统篇)pinctrl api介绍及实验

&#x1f680;返回专栏总目录 文章目录 一、pinctrl函数介绍二、设备树案例三、驱动案例 沉淀、分享、成长&#xff0c;让自己和他人都能有所收获&#xff01;&#x1f604; &#x1f4e2;本篇将介绍pinctrl api及其使用案例 。 一、pinctrl函数介绍 ①获取设备对应的 pinctrl…

TS 函数及多态

TS 能推导出函数体中的类型&#xff0c;但多数情况下无法推导出参数的类型&#xff0c;只有少数特殊情况下能根据上下文推导参数的类型。返回类型能推导出&#xff0c;不过也可以显式注解。 1 声明和调用函数 一般来说&#xff0c;在方法中的this值为调用该方法时位于点号左侧…

Vue框架学习笔记——条件渲染:v-show和v-if

文章目录 前文提要条件渲染v-showv-ifv-else-if和v-else特殊写法&#xff0c;很多个一致的v-if如何消除 总结 前文提要 本人仅做个人学习记录&#xff0c;如有错误&#xff0c;请多包涵 主要学习链接&#xff1a;尚硅谷Vue2.0Vue3.0全套教程丨vuejs从入门到精通 条件渲染 条…

Vatee万腾的数字探险之旅:vatee科技创新的新纪元

在数字时代的潮流中&#xff0c;Vatee万腾以其独特的数字探险之旅引领着科技创新的新纪元。这不仅是一次技术的进步&#xff0c;更是一场数字领域的探险&#xff0c;让我们一同探索Vatee在科技创新中的前沿地带。 Vatee万腾的数字探险起源于对未知的渴望和对创新的不懈追求。在…

使用Terraform创建Docker镜像和容器

为了实现自动化操作&#xff0c;Terraform需要明确指定所使用的提供者。因此&#xff0c;在主要的main.tf文件中&#xff0c;需要提供提供者的名称、源和版本信息。对于Docker&#xff0c;可以在main.tf中使用以下代码块。 1 Terraform配置模块 使用块和资源创建Terraform脚本…

JMeter之压力测试——混合场景并发

在实际的压力测试场景中&#xff0c;有时会遇到多个场景混合并发的情况&#xff0c;这时就需要设置不同的并发比例对不同场景请求数量的控制&#xff0c;下面提供两种方案。 一、多线程组方案 1.业务场景设计如下&#xff1a;场景A、场景B、场景C&#xff0c;三个场景按照并发…

MySQL 前瞻

数据库 是一类软件&#xff0c;这一类软件可以用来“管理数据”&#xff08;对数据进行保存&#xff0c;增删改查 [与数据结构的有什么区别呢&#xff1f;]&#xff09; 数据结构是实现增删改查的具体方式 数据库则是管理数据的软件&#xff0c;实现数据库软件内部就用到了很…

java多线程-扩展知识一:进程线程、并发并行、同步异步

1、进程 进程&#xff08;Process&#xff09;是计算机中的程序关于某数据集合上的一次运行活动&#xff0c;是系统进行资源分配的基本单位&#xff0c;是操作系统结构的基础。在早期面向进程设计的计算机结构中&#xff0c;进程是程序的基本执行实体&#xff1b;在当代面向线程…

【RLChina2023】CCF 苏州 记录

目录 RLChina介绍主旨报告专题报告智能体学习理论(专题一)智能体决策与规划(专题二)智能体框架、体系结构与训练系统(专题六)基于大语言模型的具身智能体与机器人研究 (专题八)教学报告——强化学习入门特别论坛——智能体和多智能体艺术的探索会议照片RLChina介绍 RLC…

微服务--02--Nacos注册中心

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 服务注册和发现手动发送Http请求的方式存在问题注册中心原理 Nacos注册中心配置服务注册服务发现小结&#xff1a; 服务注册和发现 手动发送Http请求的方式存在问题…

京东平台双11全品类完整销售数据回顾(京东大数据-京东数据采集-京东数据接口)

今年的双十一&#xff0c;大家依然没有等到各大平台的官方战报。 所以&#xff0c;对于绝大部分品牌、商家、咨询公司乃至有数据研究需求的小伙伴来说&#xff0c;很难了解到今年大促消费者的真实消费水平。 为此&#xff0c;鲸参谋简单整理出了10个京东大类目&#xff08;含5…

内测分发平台是否支持应用的微服务化部署

内测分发平台的微服务化部署支持是现代应用开发和部署的一个重要特性。首先我们得知道什么是微服务化部署都有哪些关键功能&#xff0c;如何实施微服务化的部署。下文以我自己理解总结了几点。 图片来源:news.gulufenfa.com 微服务是一种基于独立运行的小型服务来构建应用程序…

Java LinkedHashMap

LinkedHashMap 继承于 HashMap。在 HashMap 基础上, 维护了一条双向链表, 用来记录存入 Map 中的数据的顺序, 即存储到 Map 中的 key-value 是有序的。 解决了 HashMap 无法顺序访问的和保持插入顺序的问题。 1 LinkedHashMap 的结构定义 LinkedHashMap 是基于 HashMap 的实现…

Linux虚拟化的模式

三种虚拟化方式&#xff1a;完全虚拟化&#xff08;Full virtualization&#xff09;、硬件辅助虚拟化&#xff08;Hardware-Assisted Virtualization&#xff09;、半虚拟化&#xff08;Paravirtualization&#xff09;。 服务器上的虚拟化软件&#xff0c;多使用 qemu&#…

SpringCloudAlibaba之sentinel 流量卫兵(流控,熔断降级) ——详细讲解

目录 一、什么是sentinel 二、sentinel使用 1. sentinel dashboard的安装 2.启动 3.访问web界面 ​编辑 4.登录 三、sentinel 实时监控服务 1.创建项目引入依赖 2.配置 3.启动服务 4.访问dashboard界面查看服务监控 5.开发服务 6.启动进行调用 7.查看监控界面 四、senti…

基于helm的方式在k8s集群中部署gitlab - 部署(一)

文章目录 1. 背景说明2. 你可以学到什么&#xff1f;3. 前置条件4. 安装docker服务&#xff08;所有节点&#xff09;5. 部署k8s集群5.1 系统配置&#xff08;所有节点&#xff09;5.2 安装kubelet组件(所有节点)5.2.1 编写kubelet源5.2.2 安装kubelet5.2.3 启动kubelet 5.3 集…
最新文章