redis04Java连接redis,springboot整合redis,springboot连接redis集群,redis使用场景(作为缓存),以及阿里云搭建集群连接去中心化集群出现的坑

Java连接redis,springboot整合redis,springboot连接redis集群,redis使用场景(作为缓存),以及阿里云搭建集群连接去中心化集群出现的坑

  • Java连接redis---jedis
      • 使用jedis连接池
  • springboot整合redis
    • springboot连接StringRedisTemplate
      • 引入依赖
      • 配置在application.properties文件中
      • 测试
  • springboot连接redis
    • redis配置类
  • springboot连接redis集群
    • 连接哨兵
    • 连接去中心化集群
      • 注意:避免踩坑
  • springboot使用场景
    • 作为缓存
    • 缓存原理
    • 使用缓存注解
  • 作为分布式锁
  • 作为点赞量videaId,0 incr(videaId),排行榜,转发量。
  • 限时业务的运用

Java连接redis—jedis

注意:阿里云要在redis.conf中开启:才能进行java连接redis
protected-mode no 关闭protected-mode模式,此时外部网络可以直接访问
redis04Java连接redis,springboot整合redis,springboot连接redis集群,redis使用场景(作为缓存),以及阿里云搭建集群连接去中心化集群出现的坑_第1张图片
注意:这里要用公网ip

 Jedis jedis=new Jedis("192.168.213.122",6379);//必须运行远程连接 必须防火墙放行该端口号

依赖:

  <dependencies>
        <dependency>
            <groupId>redis.clientsgroupId>
            <artifactId>jedisartifactId>
            <version>3.3.0version>
        dependency>
 dependencies>

测试代码:

  @Test
    public void test1() {
//        必须运行远程连接,必须防火墙放行该端口号
        Jedis jedis = new Jedis("8.140.7.46", 6378);
//       关于字符串
        jedis.set("k1", "v1");
        jedis.set("k2", "v2");
        System.out.println(jedis.setnx("k1", "v1"));


//        操作key
        Set<String> keys = jedis.keys("*");
        System.out.println(keys);
        jedis.del("k2");
        jedis.expire("k2",60);
        System.out.println(jedis.ttl("k2"));

    }

使用jedis连接池

    //连接池的配置
        JedisPoolConfig config=new JedisPoolConfig();
        config.setMaxTotal(100);//设置连接池的最大连接数
        config.setMaxIdle(10);//设置最大空闲的个数
        config.setTestOnBorrow(true);//在从连接池这种获取连接对象前是否测试该对象可以。

        //创建连接池对象
        JedisPool jedisPool=new JedisPool(config,"192.168.213.188",6379);

        //获取jedis对象
        Jedis jedis = jedisPool.getResource();

        System.out.println(jedis.get("k3"));

        jedis.close();//释放资源

springboot整合redis

springboot为操作redis准备了两个工具类StringRedisTemplate和RedisTemplate。StringRedisTemplate是RedisTemplate的子类。StringRedisTemplate它的泛型key和value都是String类型。 RedisTemplate它的key value的泛型是Object。

springboot连接StringRedisTemplate

引入依赖

  <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-data-redisartifactId>
        dependency>

配置在application.properties文件中

阿里云在这里要写公网ip

spring.redis.host=192.168.213.188
spring.redis.port=6379
spring.redis.jedis.pool.max-active=20
spring.redis.jedis.pool.max-idle=8
spring.redis.jedis.pool.min-idle=0
spring.redis.jedis.pool.max-wait=20000

测试

在这里注入的是StringRedisTemplate

@Test
    void contextLoads() {
//        操作key
        Set<String> keys = stringRedisTemplate.keys("*");
        System.out.println(keys);

        stringRedisTemplate.delete("k1");
        System.out.println(stringRedisTemplate.getExpire("k3"));

//        设置过期时间
        stringRedisTemplate.expire("k3",60, TimeUnit.SECONDS);
        System.out.println(stringRedisTemplate.getExpire("k3"));
    }
    @Test
    public void testString(){
//        对字符串操作的
        ValueOperations<String, String> forValue = stringRedisTemplate.opsForValue();
        forValue.set("k1","v1");
        System.out.println(forValue.get("k1"));
        HashMap<String, String> map = new HashMap<>();
        map.put("k9","v9");
        map.put("k10","v10");
//       相当于 mset 一次存放多个字符串的value到响应的key上
        forValue.multiSet(map);


        ArrayList<String> list = new ArrayList<>();
        list.add("k1");
        list.add("k1");
        list.add("k2");
        List<String> list1 = forValue.multiGet(list);
        System.out.println(list1);
// 相当于setnx 把指定的value存放到对应的key上,如果对应的key已经存在,咋不存储,如果不存在,则存储。
        System.out.println(forValue.setIfAbsent("K2","V2"));
    }

springboot连接redis

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

redis配置类

在这里可以用于验证码,给key,value设置序列化方式,配置序列化(解决乱码的问题)

@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;
    }
}

springboot连接redis集群

连接哨兵

(1)在idea中application.properties文件添加哨兵代码

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

注意:这里的ip要为外网ip,即服务器的公网ip
在这里插入图片描述
(2)连接普通的redis,阿里云这里要填公网ip

spring.redis.host=8.140.7.42
spring.redis.port=6378

连接去中心化集群

(1) 在idea中application.properties文件添加去中心化集群代码
端口号

server.port=8888
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

注意:避免踩坑

(2)搭建去中心化集群,分配槽写8001,阿里云服务器的安全组要放行12个端口8001,8002,8003,8004,8005,8006,18001,18002,18003,18004,18005,18006。因为它默认要加上10000
redis04Java连接redis,springboot整合redis,springboot连接redis集群,redis使用场景(作为缓存),以及阿里云搭建集群连接去中心化集群出现的坑_第2张图片
以下是官网的解释:
redis04Java连接redis,springboot整合redis,springboot连接redis集群,redis使用场景(作为缓存),以及阿里云搭建集群连接去中心化集群出现的坑_第3张图片

springboot使用场景

redis04Java连接redis,springboot整合redis,springboot连接redis集群,redis使用场景(作为缓存),以及阿里云搭建集群连接去中心化集群出现的坑_第4张图片

作为缓存

1.为什么使用缓存?
减少数据库的访问频率。 提高数据的访问率。

2.什么样的数据适合放入缓存?
1.热点数据。 2. 修改频率比较低。3.安全系数低的。

缓存原理

redis04Java连接redis,springboot整合redis,springboot连接redis集群,redis使用场景(作为缓存),以及阿里云搭建集群连接去中心化集群出现的坑_第5张图片
如何使用缓存
(1)搭建一个springboot+mp的工程
(2)引入redis相关的依赖
(3)配置redis
(4)service实现类代码

@Service
public class DeptServiceI {

    @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的缓存注解。

使用缓存注解

@Cacheable(cacheNames = “findById”,key = “#deptId”) //缓存的key值 为findById,用于查询的方法。
该注解作用:会先查询缓存,如果缓存存在,则不会执行代码块。 如果缓存中不存在则执行该方法,并把该方法的返回值存放到redis中
@CacheEvict(cacheNames = “findById”,key = “#deptId”),用于删除的方法。
如果指定为 true,则在方法还没有执行的时候就清空缓存。缺省情况下,如果方法执行抛出异常,则不会清空缓存。
@CachePut(cacheNames = “findById”,key = “#dept.deptId”),用于修改的方法。
这个注解是必须执行方法体,而且会把方法体执行的结果放入到缓存中。 如果发生异常则不操作缓存。
(1)在启动类添加这个开启缓存的注解

@EnableCaching //开启缓存的注解

(2)service实现类代码

@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;
    }
}

作为分布式锁

见下篇文章

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

限时业务的运用

你可能感兴趣的:(redis,redis集群,java,redis)