Redis(二)redisTemplate

持久化

redis是内存数据库,服务器重启,数据会丢失
持久化机制:

  • RDB:默认方式,不需要进行配置
    在一定的间隔事件中,检测key的变化情况,然后持久化数据
  • AOF:日志记录的方式,记录每一条命令的操作,可以每次命令操作后,持久化数据
RDB

在redis.windows.conf文件中修改配置

# 在15分钟有至少1个key改变持久化一次
save 900 1
# 在5分钟有至少10个key改变持久化一次
save 300 10
# 在1分钟有至少 10000个key改变持久化一次
save 60 10000

持久化后会生成一个rdb文件,保存持久化的数据
可以在redis安装目录使用命令指定配置文件

redis-server.exe redis.windows.conf

AOF

编辑配置文件redis.windows.conf

appendonly默认是no,改为yes

有三个配置

#appendfsync always:每一次操作都进行持久化
appendfsync everysec:每隔一秒进行一次持久化
#appendfsync no:不进行持久化

会生成一个aof类型的持久化文件

java客户端 Jedis

一款Java操作redis数据库的工具

		<!--连接池-->
		<dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>
        <!--jedis-->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.9.3</version>
        </dependency>

Jedis操作redis的方法和redis命令相同

jedis连接池 JedisPool

getResource()方法得到jedis对象
连接池主要配置连接池参数,使用很简单。

spring-data-redis

RedisTemplate高度封装了jedis,自动管理连接池

RedisTemplate API原生Redis指令说明
public void delete(K key)DEL key [key …]删除给定的一个或多个 key
public Boolean hasKey(K key)EXISTS key检查给定 key 是否存在
public Boolean expire/expireAt(…)EXPIRE key seconds为给定 key 设置生存时间,当 key 过期时(生存时间为 0 ),它会被自动删除。
public Long getExpire(K key)TTL key以秒为单位,返回给定 key 的剩余生存时间(TTL, time to live)。

RedisTemplate中定义了对5种数据结构操作

redisTemplate.opsForValue();//操作字符串
redisTemplate.opsForHash();//操作hash
redisTemplate.opsForList();//操作list
redisTemplate.opsForSet();//操作set
redisTemplate.opsForZSet();//操作有序set

这五种类型得到对应的Operations,再去操作redis
可以直接使用boundXXXOps

BoundValueOperations
BoundSetOperations
BoundListOperations
BoundSetOperations
BoundHashOperations

opsForXXX和boundXXXOps的区别
XXX为Value的类型,前者获取一个operator,但是没有指定操作的对象(key),可以在一个连接(事务)内操作多个key以及对应的value;后者获取了一个指定的对象(key)的operator,在一个连接(事务)内只能操作这个对应的key。

RedisTemplate配置

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {

        RedisTemplate<String, Object> template = new RedisTemplate<>();
        // 配置连接工厂
        template.setConnectionFactory(factory);

        //使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)
        Jackson2JsonRedisSerializer jacksonSeial = new Jackson2JsonRedisSerializer(Object.class);

        ObjectMapper om = new ObjectMapper();
        // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jacksonSeial.setObjectMapper(om);

        // 值采用json序列化
        template.setValueSerializer(jacksonSeial);
        //使用StringRedisSerializer来序列化和反序列化redis的key值
        template.setKeySerializer(new StringRedisSerializer());

        // 设置hash key 和value序列化模式
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(jacksonSeial);
        template.afterPropertiesSet();

        return template;
    }

redis序列化策略不同会导致redisTemplate.opsForValue().get不到数据
序列化反序列化的多种选择策略


JdkSerializationRedisSerializer:POJO对象的存取场景,使用JDK本身序列化机制,将pojo类通过ObjectInputStream/ObjectOutputStream进行序列化操作,最终redis-server中将存储字节序列。是目前最常用的序列化策略。

StringRedisSerializer:Key或者value为字符串的场景,根据指定的charset对数据的字节序列编码成string,是“new String(bytes, charset)”和“string.getBytes(charset)”的直接封装。是最轻量级和高效的策略。

JacksonJsonRedisSerializer:jackson-json工具提供了javabean与json之间的转换能力,可以将pojo实例序列化成json格式存储在redis中,也可以将json格式的数据转换成pojo实例。因为jackson工具在序列化和反序列化时,需要明确指定Class类型,因此此策略封装起来稍微复杂。【需要jackson-mapper-asl工具支持】

OxmSerializer:提供了将javabean与xml之间的转换能力,目前可用的三方支持包括jaxb,apache-xmlbeans;redis存储的数据将是xml工具。不过使用此策略,编程将会有些难度,而且效率最低;不建议使用。【需要spring-oxm模块的支持】

Redis数据缓存

package org.jeecg.common.api.vo;
 
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.cache.interceptor.KeyGenerator;
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.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
 
import java.lang.reflect.Method;
import java.time.Duration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
 
 
/**
 * redis配置类
 **/
@Configuration
@EnableCaching//开启注解式缓存
//继承CachingConfigurerSupport,为了自定义生成KEY的策略。可以不继承。
public class RedisConfig extends CachingConfigurerSupport {
 
    /**
     * 生成key的策略 根据类名+方法名+所有参数的值生成唯一的一个key
     * @return
     */
    @Bean
    @Override
    public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            @Override
            public Object generate(Object target, Method method, Object... params) {
                StringBuilder sb = new StringBuilder();
                sb.append(target.getClass().getName());
                sb.append(method.getName());
                for (Object obj : params) {
                    sb.append(obj.toString());
                }
                return sb.toString();
            }
        };
    }
 
    /**
     * 管理缓存
     * @param redisConnectionFactory
     * @return
     */
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        //通过Spring提供的RedisCacheConfiguration类,构造一个自己的redis配置类,从该配置类中可以设置一些初始化的缓存命名空间
        // 及对应的默认过期时间等属性,再利用RedisCacheManager中的builder.build()的方式生成cacheManager:
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();  // 生成一个默认配置,通过config对象即可对缓存进行自定义配置
        config = config.entryTtl(Duration.ofHours(1))     // 设置缓存的默认过期时间,也是使用Duration设置
                .disableCachingNullValues();     // 不缓存空值
 
        // 设置一个初始化的缓存空间set集合
        Set<String> cacheNames = new HashSet<>();
        cacheNames.add("cache1");
        cacheNames.add("cache2");
 
        // 对每个缓存空间应用不同的配置
        Map<String, RedisCacheConfiguration> configMap = new HashMap<>();
        configMap.put("cache1", config);
        configMap.put("cache2", config.entryTtl(Duration.ofSeconds(1200)));
 
        RedisCacheManager cacheManager = RedisCacheManager.builder(redisConnectionFactory)     // 使用自定义的缓存配置初始化一个cacheManager
                .initialCacheNames(cacheNames)  // 注意这两句的调用顺序,一定要先调用该方法设置初始化的缓存名,再初始化相关的配置
                .withInitialCacheConfigurations(configMap)
                .build();
        return cacheManager;
    }
 
    @Bean
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);
 
        //使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)
        Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);
 
        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        serializer.setObjectMapper(mapper);
 
        template.setValueSerializer(serializer);
        //使用StringRedisSerializer来序列化和反序列化redis的key值
        template.setKeySerializer(new StringRedisSerializer());
        template.afterPropertiesSet();
        return template;
    }
 
    @Bean
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory factory) {
        StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
        stringRedisTemplate.setConnectionFactory(factory);
        return stringRedisTemplate;
    }
}

使用缓存


   //表示使用cache2缓存空间,key的生成策略为book+id,当id>2的时候才会使用缓存
    @Cacheable(value = "cache2",key = "'book'+#id",condition = "#id>2")
    public Book selectByPrimaryKey(Integer id) {
        return this.bookMapper.selectByPrimaryKey(id);
    }

@Cacheable: 作用是主要针对方法配置,能够根据方法的请求参数对其结果进行缓存

主要参数说明:

  1. value : 缓存的名称,在 spring 配置文件中定义,必须指定至少一个
    例如:@Cacheable(value=”mycache”) 或者 @Cacheable(value={”cache1”,”cache2”}。

  2. key :缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合,
    例如:@Cacheable(value=”testcache”,key=”#userName”)。

  3. condition :缓存的条件,可以为空

@CachePut: 作用是主要针对方法配置,能够根据方法的请求参数对其结果进行缓存,和 @Cacheable 不同的是,它每次都会触发真实查询
主要参数说明: 参数配置和@Cacheable一样

@CacheEvict: 作用是主要针对方法配置,能够根据一定的条件对缓存进行清空

主要参数说明:

  1. value , key 和 condition 参数配置和@Cacheable一样。

  2. allEntries :是否清空所有缓存内容,缺省为 false,如果指定为 true,则方法调用后将立即清空所有缓存

  3. beforeInvocation :是否在方法执行前就清空,缺省为 false,如果指定为 true,则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法执行抛出异常,则不会清空缓存

   @CacheEvict(value = "cache2",allEntries = true)
    public void clear(){
        System.out.println("cache2槽里的所有缓存被清除....");
    }

Redis集群配置

public class RedisConfig {

    protected Logger LOG = LoggerFactory.getLogger(this.getClass());
    @Value("${spring.redis.cluster.nodes}")
    private String clusterNodes;

    @Bean
    public JedisCluster getJedisCluster() {
        String[] cNodes = clusterNodes.split(",");
        LOG.info("连接redis ips-->{}", JSON.toJSONString(cNodes));
        Set<HostAndPort> nodes = new HashSet<>();
        //分割出集群节点
        for (String node : cNodes) {
            String[] hp = node.split(":");
            nodes.add(new HostAndPort(hp[0], Integer.parseInt(hp[1])));
        }
        JedisPoolConfig jedisPoolConfig = getJedisPoolConfig();
        // 最大空闲连接数, 默认8个
        jedisPoolConfig.setMaxIdle(100);
        // 最大连接数, 默认8个
        jedisPoolConfig.setMaxTotal(500);
        //最小空闲连接数, 默认0
        jedisPoolConfig.setMinIdle(0);
        // 获取连接时的最大等待毫秒数(如果设置为阻塞时BlockWhenExhausted),如果超时就抛异常, 小于零:阻塞不确定的时间,  默认-1
        jedisPoolConfig.setMaxWaitMillis(2000); // 设置2秒
        //对拿到的connection进行validateObject校验
        jedisPoolConfig.setTestOnBorrow(true);
        //创建集群对象
//        return new JedisCluster(nodes, 5000,5000,5,"seaking", jedisPoolConfig);
        return new JedisCluster(nodes, 5000,jedisPoolConfig);
    }
}

通过getJedisCluster()得到JedisCluster 去操作redis。
因为集群中链接是对一个节点连接,使用命令的时候才会去连接,所以有些单机可以是用的命令不可以用,其余使用方法和jedis相同。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值