Redis初步认识

                                            Redis初步认识2021-08-20

记录一下数据类型和对数据类型的简单操作,相关的命令可以在官网上看见,我看命令的名称也都一样。
在这里插入图片描述
在这里插入图片描述

上边是源码,下边是官网介绍的,可以对照着看,挺方便的。
数据类型:
String: redis中的基本类型,是二进制安全的(字符串不会因为存在特殊字符而导致歧义,c语言中\0表示为字符串的结束,但是redis中的字符串没有这样类似的特殊字符),可以包含任意类型的数据,比如:一个图片的或者一个对象。
可以用INCR(incr,decr,incrby)把字符串当作一个原子计数器来操作,保证原子性。
List: 简单的字符串集合,可以选择插入头部(LPUSH ),或者从尾部插入(RPUSH),一个列表最多可以放入2^32 -1个元素,访问两端的数据非常的快速,但是访问一个元素特别多的集合的中间数据还是比较慢的。可以用LPUSH操作放入一些最新的数据,然后用LRANGE去查阅最新的数据。
Set: 无序不重复的集合,增加元素,删除元素,否是包含元素都是很快的,负责度为O(1),在往set集合中添加新元素的时候,不用手动去判断是否已经包含此元素,可以很短的时间内求出两个集合 交集,并集的数据,最多包含元素同上。可以用来计算某个网站的访问量,
Hash: 字符串字段和字符串值的映射关系,可以用来表示对象,一个hash包含最多的键值对同上。一个hash所拥有的字段少于100个只需要很少的空间来存储。
Sort Set:有序集合,每个元素都关联着一个评分,这个评分就是用来排序使用的。因为元素在添加的时候就会排序,所以可以很快的查阅一个范围的数据,

maven依赖:

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
   <groupId>org.apache.commons</groupId>
   <artifactId>commons-pool2</artifactId>
</dependency>
@Bean
public RedisTemplate<String,Object> redisTemplate(LettuceConnectionFactory factory){
    RedisTemplate<String, Object> template = new RedisTemplate<>();
    template.setConnectionFactory(factory);
    //使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)
    Jackson2JsonRedisSerializer jackson = new Jackson2JsonRedisSerializer(Object.class);
    ObjectMapper om = new ObjectMapper();
    // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
    om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
    om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
    jackson.setObjectMapper(om);
    // 值采用json序列化
    template.setValueSerializer(jackson);
    //使用StringRedisSerializer来序列化和反序列化redis的key值
    template.setKeySerializer(new StringRedisSerializer());


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

使用这个序列化配置之后,自己测试了下String,List,Hash的简单存取都成功了,然后接着开始测试pipeline操作
在这里插入图片描述

尝试存好几个String 的操作出错了,报错是因为类型不支持转换,但是我看源代码确实是应该可以的,因为是继承关系。
在这里插入图片描述

后来就不转换类型了,直接用 RedisConnection类的方法进行操作,存储是成功了,但是通过pipeline操作存储成功的String的值,无法通过redisTemplate.opsForValue().get(key)获取,
在这里插入图片描述

是因为pipeline进行存储没有指定序列化,指定一下就可以了。
在这里插入图片描述

在pipeline操作查看多个键的时候,我开始是这么写的,但是每次这个redisConnection.get(xxxx)都是返回空,然后百度了半天,最终找到问题所在,是个简单的问题,但是我有点蠢了。。

redisTemplate.executePipelined(new RedisCallback<Object>() {
    @Override
    public Object doInRedis(RedisConnection redisConnection) throws DataAccessException {
        list.stream().forEach(x -> {
            redisConnection.get("string13".getBytes(StandardCharsets.UTF_8));
        });
        return null;
    }
});这段代码是我重写executePipelined方法,点进去看一下源码
public List<Object> executePipelined(RedisCallback<?> action) {
    return this.executePipelined(action, this.valueSerializer);//调用的就是下面的方法
}

public List<Object> executePipelined(RedisCallback<?> action, @Nullable RedisSerializer<?> resultSerializer) {
    return (List)this.execute((connection) -> {
        connection.openPipeline();
        boolean pipelinedClosed = false;


        List var7;
        try {
            Object result = action.doInRedis(connection);// 这个就是实际调用我重写的doInRedis方法
            if (result != null) {
                throw new InvalidDataAccessApiUsageException("Callback cannot return a non-null value as it gets overwritten by the pipeline");
            }


            List<Object> closePipeline = connection.closePipeline();
            pipelinedClosed = true;
            var7 = this.deserializeMixedResults(closePipeline, resultSerializer, this.hashKeySerializer, this.hashValueSerializer);
        } finally {
            if (!pipelinedClosed) {
                connection.closePipeline();
            }


        }


        return var7;
    });
}

然后我就进到之前看了好多遍的redisConnection.get(xxxx)的具体实现类,打断点之后发现了具体的实现方法
在这里插入图片描述

步骤一就是进入到方法,步骤二因为我是pipeline进入的,所以一直是true,所以我之前在自己重写的doInRedis方法中得到的null就是的步骤四这个地方返回的,可以看到步骤三中的get方法是将结果绑定了到connection中。再回到上面代码:

public List<Object> executePipelined(RedisCallback<?> action) {
    return this.executePipelined(action, this.valueSerializer);
}


public List<Object> executePipelined(RedisCallback<?> action, @Nullable RedisSerializer<?> resultSerializer) {
    return (List)this.execute((connection) -> {
        connection.openPipeline();
        boolean pipelinedClosed = false;


        List var7;
        try {
            Object result = action.doInRedis(connection); //实际查询的结果此时是在这个connection中的 本来我想是不是result中的 但是下面代码并没有用到result这个变量 只是继续用了connection
            if (result != null) {
                throw new InvalidDataAccessApiUsageException("Callback cannot return a non-null value as it gets overwritten by the pipeline");
            }


            List<Object> closePipeline = connection.closePipeline();//只有这块用到了connection
            pipelinedClosed = true;
            var7 = this.deserializeMixedResults(closePipeline, resultSerializer, this.hashKeySerializer, this.hashValueSerializer);//这个方法也 间接用到了connection,然后看一下这个方法的具体实现
        } finally {
            if (!pipelinedClosed) {
                connection.closePipeline();
            }


        }


        return var7;
    });
}
@Nullable                                       
private List<Object> deserializeMixedResults(@Nullable List<Object> rawValues, @Nullable RedisSerializer valueSerializer, @Nullable RedisSerializer hashKeySerializer, @Nullable RedisSerializer hashValueSerializer) {
    if (rawValues == null) {
        return null;
    } else {
        List<Object> values = new ArrayList();
        Iterator var6 = rawValues.iterator();这个地方就很明显了,是根据具体子元素的类型判断一下 然后反序列化一下,最终就是根据这个结果集返回的
        

        while(true) {
            while(var6.hasNext()) {
                Object rawValue = var6.next();
                if (rawValue instanceof byte[] && valueSerializer != null) {
                    values.add(valueSerializer.deserialize((byte[])((byte[])rawValue)));
                } else if (rawValue instanceof List) {
                    values.add(this.deserializeMixedResults((List)rawValue, valueSerializer, hashKeySerializer, hashValueSerializer));
                } else if (rawValue instanceof Set && !((Set)rawValue).isEmpty()) {
                    values.add(this.deserializeSet((Set)rawValue, valueSerializer));
                } else if (rawValue instanceof Map && !((Map)rawValue).isEmpty() && ((Map)rawValue).values().iterator().next() instanceof byte[]) {
                    values.add(SerializationUtils.deserialize((Map)rawValue, hashKeySerializer, hashValueSerializer));
                } else {
                    values.add(rawValue);
                }
            }


            return values;
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值