精华内容
下载资源
问答
  • SpringBoot连接Redis集群

    2021-01-19 22:28:12
    文章目录1. 依赖2. 修改配置文件3. 创建RedisClusterConfig4. 测试 1. 依赖 <dependency> <groupId>redis.clients</groupId> <artifactId>...#redis集群节点信息 spring.redi

    1. 依赖

        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>
    

    2. 修改配置文件

    server.port=100
    
    #redis集群节点信息
    spring.redis.cluster.nodes=192.168.25.132:6379,192.168.25.132:6380,192.168.25.133:6379,192.168.25.133:6380,192.168.25.134:6379,192.168.25.134:6380
    #redis连接密码(默认空)
    spring.redis.password=
    #redis连接池最大连接数(使用负值表示没有限制)
    spring.redis.jedis.pool.max-active=20
    #redis连接池最大阻塞等待时间(使用负值表示没有限制)
    spring.redis.jedis.pool.max-wait=-1
    #redis连接池最大空闲连接
    spring.redis.jedis.pool.max-idle=200
    #redis连接池最小空闲连接
    spring.redis.jedis.pool.min-idle=20
    #redis连接超时时间(毫秒)
    spring.redis.timeout=10000
    

    3. 创建RedisClusterConfig

    @Configuration
    public class RedisClusterConfig {
    
        @Value("${spring.redis.cluster.nodes}")
        private String clusterNodes;
    
        @Value("${spring.redis.database}")
        private int database;
    
        @Value("${spring.redis.timeout}")
        private int timeout;
    
        @Value("${spring.redis.jedis.pool.max-idle}")
        private int maxIdle;
    
        @Value("${spring.redis.jedis.pool.min-idle}")
        private int minIdle;
    
        @Value("${spring.redis.jedis.pool.max-active}")
        private int maxActive;
    
        @Value("${spring.redis.jedis.pool.max-wait}")
        private long maxWait;
    
        @Bean
        public JedisCluster getJedisCluster() {
            return new JedisCluster(getNodes(), timeout, poolConfig());
        }
    
        private JedisPoolConfig poolConfig() {
            JedisPoolConfig config = new JedisPoolConfig();
            config.setMaxIdle(maxIdle);
            config.setMinIdle(minIdle);
            config.setMaxTotal(maxActive);
            config.setMaxWaitMillis(maxWait);
            return config;
        }
    
        private Set<HostAndPort> getNodes() {
            String[] cNodes = clusterNodes.split(",");
            Set<HostAndPort> nodes = new HashSet<HostAndPort>();
            // 分割出集群节点
            String[] hp;
            for (String node : cNodes) {
                hp = node.split(":");
                nodes.add(new HostAndPort(hp[0], Integer.parseInt(hp[1])));
            }
            return nodes;
        }
    }
    

    4. 测试

    @RestController
    @RequestMapping("/redis/cluster")
    public class RedisClusterController {
        @Autowired
        private JedisCluster jedisCluster;
    
        @GetMapping("/set")
        public void set(@RequestParam("key") String key, @RequestParam("value") String value){
            jedisCluster.set(key, value);
        }
    }
    

    这边就不演示了,分别访问以下2个地址,能得到结果说明正常:

    http://localhost:100/redis/cluster/set?key=name&value=zhangsan

    http://localhost:100/redis/cluster/get?key=name

    展开全文
  • Java连接redis,springboot连接redis,springboot连接redis集群,redis使用场景及面试题1. springboot连接redis2. springboot连接redis集群。3. redis使用场景(1)作为缓存。(2)作为分布式锁(3)作为点赞量...

    1. springboot连接redis

    使用redisTemplate该类可以存放任意类型的数据,但是该类型的数据必须实现序列,获取redis中对应的数据时,会进行反序列化。 如果使用RedisTemplate建议大家指定key,value,以及hashkey的序列化方式。

    package com.dxl.config;
    
    import com.fasterxml.jackson.annotation.JsonAutoDetect;
    import com.fasterxml.jackson.annotation.PropertyAccessor;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.springframework.cache.CacheManager;
    import org.springframework.cache.annotation.CachingConfigurerSupport;
    import org.springframework.cache.annotation.EnableCaching;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.data.redis.cache.RedisCacheConfiguration;
    import org.springframework.data.redis.cache.RedisCacheManager;
    import org.springframework.data.redis.connection.RedisConnectionFactory;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.data.redis.serializer.*;
    
    import java.time.Duration;
    
    @EnableCaching
    @Configuration
    public class RedisConfig extends CachingConfigurerSupport {
        //比如验证码
        @Bean
        public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
            RedisTemplate<String, Object> template = new RedisTemplate<>();
            RedisSerializer<String> redisSerializer = new StringRedisSerializer();
            Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
            ObjectMapper om = new ObjectMapper();
            om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
            om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
            jackson2JsonRedisSerializer.setObjectMapper(om);
            template.setConnectionFactory(factory);
            //key序列化方式
            template.setKeySerializer(redisSerializer);
            //value序列化
            template.setValueSerializer(jackson2JsonRedisSerializer);
            //value hashmap序列化
            template.setHashValueSerializer(jackson2JsonRedisSerializer);
            return template;
        }
    
        @Bean
        public CacheManager cacheManager(RedisConnectionFactory factory) {
            RedisSerializer<String> redisSerializer = new StringRedisSerializer();
            Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
            //解决查询缓存转换异常的问题
            ObjectMapper om = new ObjectMapper();
            om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
            om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
            jackson2JsonRedisSerializer.setObjectMapper(om);
            // 配置序列化(解决乱码的问题),过期时间600秒
            RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                    .entryTtl(Duration.ofSeconds(600)) //缓存过期10分钟 ---- 业务需求。
                    .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))//设置key的序列化方式
                    .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer)) //设置value的序列化
                    .disableCachingNullValues();
            RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
                    .cacheDefaults(config)
                    .build();
            return cacheManager;
        }
    }
    

    2. springboot连接redis集群。

    (1)哨兵

    spring.redis.sentinel.master=mymaster
    spring.redis.sentinel.nodes=192.168.213.188:26379
    

    (2) 去中心化集群

    spring.redis.cluster.nodes=192.168.213.188:8001,192.168.213.188:8002,192.168.213.188:8003,192.168.213.188:8004,192.168.213.188:8005,192.168.213.188:8006
    

    3. redis使用场景

    (1)作为缓存。

    1.为什么使用缓存?
       减少数据库的访问频率。 提高数据的访问率。
    
    2.什么样的数据适合放入缓存?
        1.热点数据。 2. 修改频率比较低。3.安全系数低的。
    

    缓存的原理:

    在这里插入图片描述

    如何使用缓存

    (1)搭建一个springboot+mp的工程

    (2)引入redis相关的依赖

    (3)配置redis

    (4)service代码

    package com.dxl.service;
    
    import com.dxl.dao.DeptDao;
    import com.dxl.entity.Dept;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.stereotype.Service;
    
    import javax.annotation.Resource;
    
    
    @Service
    public class DeptService {
    
        @Resource
        private DeptDao deptDao;
    
        @Autowired
        private RedisTemplate redisTemplate;
    
        public Dept findById(Integer deptId){
            //1.从缓存中查询该数据
            Object o = redisTemplate.opsForValue().get("findById::" + deptId);
            if(o!=null){//表示从缓存中获取该数据
                return (Dept) o;
            }
            Dept dept = deptDao.selectById(deptId);
            redisTemplate.opsForValue().set("findById::"+deptId,dept);//把查询的结果放入缓存
            return dept;
        }
    
    
        //数据库和缓存同步问题!
        public int delete(Integer deptId){
            redisTemplate.delete("findById::"+deptId);//删除缓存
            int i = deptDao.deleteById(deptId);
            return i;
        }
    
        public int update(Dept dept){
            redisTemplate.delete("findById::"+dept.getDeptId());//删除缓存
            int i = deptDao.updateById(dept);
            redisTemplate.opsForValue().set("findById::"+dept.getDeptId(),dept);
            return i;
        }
    }
    

    上面这些代码每次都要写很多与业务无关的一些非业务代码!

    (1)使用aop来解决---->动态代理(动态代理的实现模式基于JDK动态代理)
    https://blog.csdn.net/qq_39470733/article/details/77315010
    (2)基于spring的缓存注解。
    
    package com.dxl;
    
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cache.annotation.EnableCaching;
    
    @SpringBootApplication
    @MapperScan(basePackages = "com.ykq.dao")
    @EnableCaching //开启缓存的注解
    public class SpringbootRedis02Application {
    
        public static void main(String[] args) {
            SpringApplication.run(SpringbootRedis02Application.class, args);
        }
    
    }
    
    
    
    package com.dxl.service;
    
    import com.dxl.dao.DeptDao;
    import com.dxl.entity.Dept;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.cache.annotation.CacheEvict;
    import org.springframework.cache.annotation.CachePut;
    import org.springframework.cache.annotation.Cacheable;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.stereotype.Service;
    
    import javax.annotation.Resource;
    
    
    @Service
    public class DeptService {
    
        @Resource
        private DeptDao deptDao;
    
        //该注解作用:会先查询缓存,如果缓存存在,则不会执行代码块。 如果缓存中不存在则执行该方法,并把该方法的返回值存放到redis中
        @Cacheable(cacheNames = "findById",key = "#deptId")  //缓存的key值 为findById
        public Dept findById(Integer deptId){
            System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
            Dept dept = deptDao.selectById(deptId);
            return dept;
        }
    
    
        //数据库和缓存同步问题!
        // beforeInvocation:是否在方法执行前就清空,缺省为 false,
        // 如果指定为 true,则在方法还没有执行的时候就清空缓存。缺省情况下,如果方法执行抛出异常,则不会清空缓存。
        @CacheEvict(cacheNames = "findById",key = "#deptId")
        public int delete(Integer deptId){
            int i = deptDao.deleteById(deptId);
            return i;
        }
    
        //这个注解是必须执行方法体,而且会把方法体执行的结果放入到缓存中。 如果发生异常则不操作缓存。
        @CachePut(cacheNames = "findById",key = "#dept.deptId")
        public Dept update(Dept dept){
            int i = deptDao.updateById(dept);
            return dept;
        }
    }
    

    (2)作为分布式锁

    (3)作为点赞量videaId,0 incr(videaId),排行榜,转发量。

    什么是计数器,如电商网站商品的浏览量、视频网站视频的播放数等。为了保证数据实时效,每次浏览都得给+1,并发量高时如果每次都请求数据库操作无疑是种挑战和压力。Redis提供的incr命令来实现计数器功能,内存操作,性能非常好,非常适用于这些计数场景 。 
    
    关系型数据库在排行榜方面查询速度普遍偏慢,所以可以借助redis的SortedSet进行热点数据的排序。 在奶茶活动中,我们需要展示各个部门的点赞排行榜, 所以我针对每个部门做了一个SortedSet,然后以用户的openid作为上面的username,以用户的点赞数作为上面的score, 然后针对每个用户做一个hash, 通过zrangebyscore就可以按照点赞数获取排行榜,然后再根据username获取用户的hash信息,这个当时在实际运用中性能体验也蛮不错的。 
    

    (4)限时业务的运用

    redis中可以使用expire命令设置一个键的生存时间,到时间后redis会删除它。利用这一特性可以运用在限时的优惠活动信息、手机验证码等业务场景。 
    

    使用redis作为分布式锁。

    锁场景:

    package com.dxl.distributedlock.service;
    
    import com.dxl.distributedlock.dao.StockDao;
    import com.dxl.distributedlock.entity.Stock;
    import org.springframework.stereotype.Service;
    
    import javax.annotation.Resource;
    
    
    @Service
    public class StockService02 {
    
        @Resource
        private StockDao stockDao;
    
        public String decrStock(Integer productId) {//synchronized () 同步方法    同步代码块
             //查询对应的id的库存
            synchronized (this) {
                Stock stock = stockDao.selectById(productId);
                if (stock.getNum() > 0) {
                    //根据id修改库存
                    stock.setNum(stock.getNum() - 1);
                    stockDao.updateById(stock);
                    System.out.println("库存剩余:" + (stock.getNum()));
                    return "库存减少成功";
                } else {
                    return "库存不足";
                }
            }
        }
    }
    

    这种锁不适合分布式项目。

    在这里插入图片描述

    使用redis解决分布式锁的问题

    package com.dxl.distributedlock.service;
    
    import com.dxl.distributedlock.dao.StockDao;
    import com.dxl.distributedlock.entity.Stock;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.redis.core.StringRedisTemplate;
    import org.springframework.stereotype.Service;
    
    import javax.annotation.Resource;
    import java.util.concurrent.TimeUnit;
    
    
    @Service
    public class StockService {
    
        @Resource
        private StockDao stockDao;
    
        @Autowired
        private StringRedisTemplate redisTemplate;
    
        public String decrStock(Integer productId) {//synchronized () 同步方法    同步代码块
            Boolean flag = redisTemplate.opsForValue().setIfAbsent("product::" + productId, "ykq",30, TimeUnit.SECONDS);
            //查询对应的id的库存
             if(flag) {//获取锁了
                 try {
                     Stock stock = stockDao.selectById(productId);
                     if (stock.getNum() > 0) {
                         //根据id修改库存
                         stock.setNum(stock.getNum() - 1);
                         stockDao.updateById(stock); //异常发生
    //                   int c=10/0;
                         System.out.println("库存剩余:" + (stock.getNum()));
                         return "库存减少成功";
                     } else {
                         return "库存不足";
                     }
                 }catch (Exception e){
                      throw  new RuntimeException(e.getMessage());
                 }
                 finally {
                     redisTemplate.delete("product::" + productId);//释放锁资源 一定再finally
                 }
             }else{
                 System.out.println("服务器正忙请稍后再试..........");
                 return "服务器正忙请稍后再试..........";
             }
        }
    }
    

    使用第三方组件redisson-----专门用于解决分布式问题。

           <dependency>
                <groupId>org.redisson</groupId>
                <artifactId>redisson</artifactId>
                <version>3.13.4</version>
            </dependency>
    
       @Bean
        public RedissonClient getRedisson(){
            Config config=new Config();
            config.useSingleServer().setAddress("redis://192.168.213.188:6379");
            RedissonClient redissonClient = Redisson.create(config);
            return redissonClient;
        }
    
    package com.dxl.distributedlock.service;
    
    import com.dxl.distributedlock.dao.StockDao;
    import com.dxl.distributedlock.entity.Stock;
    import org.redisson.Redisson;
    import org.redisson.api.RLock;
    import org.redisson.api.RedissonClient;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.redis.core.StringRedisTemplate;
    import org.springframework.stereotype.Service;
    
    import javax.annotation.Resource;
    import java.util.concurrent.TimeUnit;
    
    
    @Service
    public class StockService {
    
        @Resource
        private StockDao stockDao;
    
        @Autowired
        private RedissonClient redisson; 
    
        public String decrStock(Integer productId) {//synchronized () 同步方法    同步代码块
            RLock lock = redisson.getLock("product::" + productId);//获取锁对象
            try {
                lock.tryLock(60,20,TimeUnit.SECONDS); //自己别设置时间。
                Stock stock = stockDao.selectById(productId);
                if (stock.getNum() > 0) {
                    //根据id修改库存
                    stock.setNum(stock.getNum() - 1);
                    stockDao.updateById(stock); //异常发生
    //                   int c=10/0;
    //                Thread.sleep(35000);
                    System.out.println("库存剩余:" + (stock.getNum()));
                    return "库存减少成功";
                } else {
                    return "库存不足";
                }
            }catch (Exception e){
                 throw  new RuntimeException(e.getMessage());
            }
            finally {
                lock.unlock();
            }
        }
    }
    

    4. redis的面试题

    1. redis缓存穿透? 如何避免缓存穿透。
       (1)数据库中没有该记录,而缓存中没有该记录。而这时有人恶意访问这种数据。 直接访问数据库。
    
    解决方案:
       (1) 如果数据库中不存在该对象,则往缓存中放入一个空对象,并且设置很短的过期时间。
       
    2.缓存的雪崩?如何避免?
      (1)再某一时刻,缓存中没有该记录,而这时会有大量的请求。这些请求打压到数据库。
           比如: 项目刚刚上线。------预访问热点数据。
                 某一个缓存的时间到了。----> 失效时间是一个散列值。
                 使用队列: ----->每次有限的请求访问数据库。
                 
    
    展开全文
  • springboot连接redis集群

    2021-03-22 20:54:26
    开启redis服务和客户端 查看下当前redis的进程 [root@localhost ~]# ps -ef | grep redis 启动redis服务 [root@localhost ~]# cd /opt/redis-5.0.4 [root@localhost redis-5.0.4]# redis-server redis.conf 再...

    开启redis服务和客户端

    查看下当前redis的进程

    [root@localhost ~]# ps -ef | grep redis
    

    在这里插入图片描述

    启动redis服务

    [root@localhost ~]# cd /opt/redis-5.0.4
    [root@localhost redis-5.0.4]# redis-server redis.conf
    

    在这里插入图片描述

    再查看下reids的服务进程

    在这里插入图片描述

    启动redis-cli

    [root@localhost redis-5.0.4]# redis-cli -h 192.168.25.10 -p 6379
    

    查看下keys

    192.168.25.10:6379> keys *
    1) "name"
    2) "age"
    

    使用 java 直接连接 redis 单机版

    1.打开 IDEA ,创建maven项目 test_redis

    在这里插入图片描述

    点击 Enable Auto-Import, 自动引入依赖

    2.在pom.xml中添加 redis单机版依赖

    
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.fan</groupId>
        <artifactId>test_redis</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <dependencies>
        	<dependency>
                <groupId>redis.clients</groupId>
                <artifactId>jedis</artifactId>
                <version>3.3.0</version>
            </dependency>
        </dependencies>
    </project>
    

    3.创建redis的测试类

    package com.fan;
    
    import redis.clients.jedis.Jedis;
    
    /**
     * 测试java 连接redis
     */
    public class TestRedis {
        public static void main(String[] args) {
            Jedis jedis = new Jedis("192.168.25.10",6379);//参数1为 ip ,参数2为端口号
            //测试 redis 服务是否能正常连通
            String pang = jedis.ping();
            System.out.println(pang);
        }
    }
    
    
    

    测试运行

    在这里插入图片描述

    连接成功。

    集群的节点也可以以单机的方式连接

    在这里插入图片描述

    设置值

    package com.fan;
    
    import redis.clients.jedis.Jedis;
    
    /**
     * 测试java 连接redis
     */
    public class TestRedis {
        public static void main(String[] args) {
            Jedis jedis = new Jedis("192.168.25.10",6379);//参数1为 ip ,参数2为端口号
            //测试 redis 服务是否能正常连通
            String pang = jedis.ping();
            System.out.println(pang);
    
            //设置key-vale值
            String set = jedis.set("name", "zhangsan");
            System.out.println("返回值: "+set); //返回值为 OK
    
            //获取key的值
            String name = jedis.get("name");
            System.out.println("name: "+name);
    
            //向list1添加值
            Long list1 = jedis.lpush("list1", "3", "4", "5");
            System.out.println(list1);
    
            //设置key的过期时间
            jedis.expire("name",10);//可以在xshello中测试 tcl name,多执行几次看下效果
            //使用过之后关闭连接
            jedis.close();
        }
    }
    
    

    在这里插入图片描述

    在XShell中执行 ttl name测试

    在这里插入图片描述

    注意: redis 服务 配置文件的bind属性必须是局域网ip 保护模式必须关闭

    使用springboot 连接 redis 集群

    一般是把redis集群当做spring boot 的缓存工具。

    在service方法里访问的很多东西,有可能很少发生变化,每次查询数据库会比较慢。

    可以在第一次查询的时候放到 redis 集群里面,下次会自动判断 redis 集群里有没有这块儿数据,有的话直接拿来用;没有的话,再去查数据库。

    打开IDEA, 创建maven项目test_redis_02

    第一步,添加依赖

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.fan</groupId>
        <artifactId>test_redis_02</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
                <version>2.2.0.RELEASE</version>
            </dependency>
            <!--springboot集成redis的依赖-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
                <version>2.2.0.RELEASE</version>
            </dependency>
            <!--mybatis-plus依赖-->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>3.3.1</version>
            </dependency>
            <!--mysql驱动依赖-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>8.0.20</version>
            </dependency>
            <!--数据源-->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>1.2.1</version>
            </dependency>
            <!--lombok依赖-->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.18.18</version>
            </dependency>
        </dependencies>
    </project>
    

    补充:安装 lombok依赖后,需要安装 lombok 插件,

    在这里插入图片描述

    使用lombok ,后面创建实体类不用再写get、set等方法了。

    第二步、写配置文件 application.properties

    在resources目录下,新建 application.properties文件

    #连接数据库的配置
    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    spring.datasource.url=jdbc:mysql://localhost:3306/aaa?useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=GMT%2B8
    spring.datasource.username=root
    spring.datasource.password=123456
    
    #在控制台显示sql语句
    mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
    
    #指定redis中的集群节点
    spring.redis.cluster.nodes=192.168.25.10:7001,192.168.25.10:7002,192.168.25.10:7003,192.168.25.10:7004,192.168.25.10:7005,192.168.25.10:7006
    

    第三步、写启动类

    package com.fan;
    
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cache.annotation.EnableCaching;
    
    /**
     * springboot 启动类
     */
    @SpringBootApplication
    @MapperScan("com.fan.dao") //扫描dao接口文件
    //启动spring boot的缓存机制
    @EnableCaching
    public class WebStarter {
        public static void main(String[] args) {
            SpringApplication.run(WebStarter.class,args);
        }
    }
    
    

    第四步、把要缓存的实体类实现序列化接口

    package com.fan.entity;
    
    import lombok.Data;
    
    import java.io.Serializable;
    
    /**
     * 用户管理实体类
     */
    @Data //lombok注解
    public class Users implements Serializable {
        private Long id; //编号
        private String username;//用户名
        private String password;//密码
    }
    
    

    第五步、创建dao接口

    package com.fan.dao;
    
    import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    import com.fan.entity.Users;
    
    /**
     * 用户管理dao接口
     */
    public interface UsersDao extends BaseMapper<Users> {
    }
    
    

    第六步、创建service层

    package com.fan.service;
    
    import com.fan.dao.UsersDao;
    import com.fan.entity.Users;
    import org.springframework.stereotype.Service;
    
    import javax.annotation.Resource;
    import java.util.List;
    
    /**
     * 用户管理servcie实现类
     */
    @Service
    public class UsersService {
    
        @Resource
        private UsersDao usersDao;
    
        /**
         * 查询所有的用户信息
         * @return
         */
        public List<Users> listAll(){
            List<Users> users = usersDao.selectList(null);
            return users;
        }
    }
    
    

    第七步、创建用户管理控制器

    package com.fan.controller;
    
    import com.fan.entity.Users;
    import com.fan.service.UsersService;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import javax.annotation.Resource;
    import java.util.List;
    
    /**
     * 用户管理控制器
     */
    @RestController
    public class UsersController {
    
        @Resource
        private UsersService usersService;
    
        /**
         * 查询所有用户
         * @return
         */
        @RequestMapping("/listAll")
        public List<Users> listAll(){
            return usersService.listAll();
        }
    }
    
    

    第八步、启动测试

    运行项目的启动类。

    在浏览器中输入 http://localhost:8080

    在这里插入图片描述

    可以看到idea的控制台打印显示了 sql语句

    在这里插入图片描述

    在要缓存数据的方法上加 springboot 提供的缓存注解

    @Cacheable

    指如果redis缓存中有数据,就直接从缓存中取数据,如果没有数据,去数据库查询,往缓存中放一份,然后再返回数据。

    第一次访问这个方法,缓存没有数据,去查询数据 库。第二次访问,缓存中有数据,就不用再查询数据库,查缓存就可以了。

    第一次启动访问时,控制台显示查询sql语句的信息。

    在浏览器中访问 http://localhost:8080/listAll

    清除控制台信息。再访问 http://localhost:8080/listAll,可以发先idea控制台不再打印sql信息。说明再第二次访问的时候直接查询页面缓存。

    连接redis-cli, 看下数据库特征

    [root@localhost ~]# redis-cli -c -h 192.168.25.10 -p 7001
    192.168.25.10:7001> keys *
    1) "listAll::SimpleKey []"
    
    192.168.25.10:7001> 
    
    

    在@Cacheable注解添加参数 key=“test”

    重新启动,测试访问

    在这里插入图片描述

    idea控制台也有报错信息, 提示 test 属性或字段在spring缓存中不能被发现,不是公共的…

    在这里插入图片描述

    key对应的是一个变量

    key= “‘test’”

    在这里插入图片描述

    重新启动测试访问

    在这里插入图片描述

    idea控制台打印显示sql日志信息

    在这里插入图片描述

    再看下redis中的数据库的特征

    在这里插入图片描述
    UsersController

        @RequestMapping("/findById")
        public Users findById(Long id){
            Users users = usersService.findById(id);
            return users;
        }
    

    UsersService

        /**
         * 根据用户id 查询用户信息
         * @param id
         * @return
         */
        @Cacheable(value = "findById",key = "#id",condition = "#id%2==0")  //condition 条件
        public Users findById(Long id){
            Users users = usersDao.selectById(id);
            return users;
        }
    

    id为奇数

    在这里插入图片描述

    再运行还会在控制台打印sql日志信息

    在这里插入图片描述

    可以看到没有存到数据库

    在这里插入图片描述

    清除控制台信息

    id为偶数

    在这里插入图片描述

    就不再查询数据库,直接查询redis

    在这里插入图片描述

    @CachePut

    无论缓存中是否有数据,都把缓存覆盖一次,也就是更新缓存。

    @CacheEvict

    每次执行方法 都会把指定的key的缓存清空

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TSvdlxVc-1616416717292)(.\img\26.png)]

    如果要清除 listAll的结果,可以写个方法

    UsersService.java

    //调用这个方法的时候会把listAll的请求的缓存清除掉
        @CacheEvict(value = "listAll")
        public void clearListAll(){
            System.out.println("清空listAll缓存");
        }
    

    UsersController.java

        /**
         * 根据用户id 查询用户信息
         * @return
         */
        @RequestMapping("/clearListAll")
        public String clearListAll(){
            usersService.clearListAll();
            return "success";
        }
    

    启动测试,在浏览器中访问 http://localhost:8080/clearListAll

    在这里插入图片描述

    看下redis缓存

    在这里插入图片描述

    可以看到把不带任何参数、不带key的listAll清除掉了。

    把所有listAll开头的都删除掉, 添加 allEntries = true

    allEntries作用就是忽略key 的值

      	@CacheEvict(value = "listAll",allEntries = true)
        public void clearListAll(){
            System.out.println("清空listAll缓存");
        }
    

    在这里插入图片描述

    以上两个注解用的不多,用的比较多的是:

    spring boot 启用缓存之后为我们在spring 容器中创建的一个内置对象 RedisTemplate

    UsersService.java

        @Autowired
        private RedisTemplate redisTemplate; //相当于Jedis
    
        /**
         * 测试redisTemplate
         */
        public void testRedisTemplate(){
            System.out.println(this.redisTemplate);
        }
    

    在控制器中调用这个方法

        /**
         * 测试redisTemplate
         * @return
         */
        @RequestMapping("/testRedisTemplate")
        public String testRedisTemplate(){
            usersService.testRedisTemplate();
            return "success";
        }
    

    启动调试,打断点

    在这里插入图片描述

    在这里插入图片描述

        /**
         * 测试redisTemplate
         */
        public void testRedisTemplate(){
            this.redisTemplate.opsForValue().set("test","value",1000, TimeUnit.SECONDS);//操作string类型数据
            this.redisTemplate.expire("test",4000,TimeUnit.SECONDS);
        }
    
    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 11,137
精华内容 4,454
关键字:

springboot连接redis集群

redis 订阅
spring 订阅