本文介绍: ☆动态配置这个配置可以轻松的跟新的,把配置写到数据库,Redis配置中心(Nacos,Apollospring Cloud config)(问题:如果服务器数据太多,ip可控制)配置,写死配置,每个服务器执行定时任务,但是只有ip符合配置的才真实执行业务逻辑,其他的直接返回分离定时任务,把控制定时任务从主程序中拆开(成本太大)分布式锁【只有抢到锁的服务器才能执行定时任务

java分布式&锁&分布式

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

分布式

  1. 为什么实现分布式
  2. 分布锁实现(核心思想,先来server数据改成自己标识,后来的人发现标识已经存在等待
    1. Zookeeper实现

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

  1. 原因

  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&gt;
                    <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();
                    }
                }
            }
        }
        
        

原文地址:https://blog.csdn.net/weixin_52154534/article/details/134642719

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_40958.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注