繁体   English   中英

使用redis进行Spring引导缓存,key有\\xac\\xed\\x00\\x05t\\x00\\x06

[英]Spring boot caching with redis,key have \xac\xed\x00\x05t\x00\x06

我想使用 Spring 缓存 @Cacheable 来管理缓存。 而真正的缓存是redis。

我的代码是这样的:

@PostMapping("/post")
@CachePut(value = "abc", key = "#key")
public String putInRedis(@RequestParam String key, @RequestParam String value) {
    saveInDB(key, value);

    return value;
}

@GetMapping("/get")
@Cacheable(value = "abc", key = "#key")
public String queryRedis(@RequestParam String key) {

    return findByKey(key);
}

在我收到帖子请求之后

本地主机:8080/post?key=key&value=value

redis 服务器出现一个奇怪的key

127.0.0.1:6379> keys *
1) "abc:\xac\xed\x00\x05t\x00\x03key"
127.0.0.1:6379> GET "abc:\xac\xed\x00\x05t\x00\x03key"
"\xac\xed\x00\x05t\x00\x05value"

弹簧缓存

奇怪的redis-key-with-spring-data-jedis

如何设置@Cacheable 的 Serializer 像 StringRedisTemplate 默认值:

public StringRedisTemplate() {
    RedisSerializer<String> stringSerializer = new StringRedisSerializer();
    setKeySerializer(stringSerializer);
    setValueSerializer(stringSerializer);
    setHashKeySerializer(stringSerializer);
    setHashValueSerializer(stringSerializer);
}

我的 application.properties:

spring.redis.host=localhost
spring.redis.password=
spring.redis.port=6379

构建.gradle

group 'io.freezhan'
version '1.0-SNAPSHOT'

buildscript {
    repositories {
        maven {
            url 'https://plugins.gradle.org/m2/'
        }
    }
    dependencies {
        classpath 'org.springframework.boot:spring-boot-gradle-plugin:1.4.0.RELEASE'
    }
}

task wrapper(type: Wrapper) {
    gradleVersion = '2.13'
    distributionUrl = "https://services.gradle.org/distributions/gradle-$gradleVersion-all.zip"
}

apply plugin: 'java'
apply plugin: 'spring-boot'

sourceCompatibility = 1.5

repositories {
    mavenCentral()
}

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web") {
        exclude module: "spring-boot-starter-tomcat"
    }
    compile("org.springframework.boot:spring-boot-starter-data-redis")
    compile("org.springframework.boot:spring-boot-starter-jetty")
    compile("org.springframework.boot:spring-boot-starter-actuator")
    compile 'org.projectlombok:lombok:1.16.10'
    testCompile("junit:junit")
}

创建一个Redis模板

private RedisTemplate<String, ?> createRedisTemplateForEntity() {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
        redisTemplate.setConnectionFactory(getRedisConnectionFactory());
        redisTemplate.setHashValueSerializer(new StringRedisSerializer());
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.afterPropertiesSet();

    return redisTemplate;
}

为什么要创建一个奇怪的字符串作为键?

密钥是根据方法中存在的参数属性创建的,该属性被注释为可缓存。 这就是spring从redis读取缓存值的方式。

Spring的缓存功能允许使用不同的缓存实现。 Redis是其中之一。 它可以与类RedisCacheManager一起使用。 Spring文档说:

如果Redis可用并已配置,则RedisCacheManager将自动配置。

这是我建议影响Redis(缓存)集成的方法:

  1. 自己将RedisCacheManager定义为bean。

  2. RedisTemplate传递给RedisTemplate的构造RedisCacheManager

我在Internet上使用编程配置找到了一个示例 还有一个使用基于XML的配置的示例

就像mm759的答案:

  1. 自己将RedisCacheManager定义为bean。

    1. 将RedisTemplate传递给RedisCacheManager的构造函数。

此代码将解决我的问题:

package io;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * Created by freezhan on 16/9/5.
 */
@Configuration
public class CacheConfig {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Bean
    public CacheManager cacheManager() {
        RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
        return cacheManager;
    }

}

和redis存储是这样的:

在此处输入图片说明

这是我的两分钱。 🪙🏛️

TL; 博士
假设您正在寻找一种解决方案来删除所有这些奇怪的键。 不要浪费时间编写单行 bash 解决方案。 这行不通, redis-cli KEYS "user*" | xargs redis-cli DEL redis-cli KEYS "user*" | xargs redis-cli DEL (来源: 如何删除密钥? )。 您的密钥是二进制格式的管道,它们不会产生预期的结果。 扩展创建密钥的脚本的功能以删除它们(Think Python、Java、Go 等)。 或者,如果您负担得起,则删除所有键redis-cli flushall (来源: 如何使用 Redis 原子地删除与模式匹配的键

就将您的密钥作为二进制数据而言,我不确定有什么好处(重复,二进制密钥,而不是数据)。 因为,结果可能证明它的空间效率和时间效率低于预期,至少根据这些帖子, do-storing-plain-text-data-take-up-less-space-than-storing-the-等效混乱are-binary-storage-methods-more-efficient-than-text-based-ones 当然,如果您有意转换了密钥。

如果您希望将密钥设为字符串格式,请在 Redis 模板上将密钥序列化器设置为StringRedisSerializer ,如@Rohith K的回答中所指出的。 这将使您能够使用上面引用的模式匹配命令来删除键。

redisTemplate.setKeySerializer(new StringRedisSerializer());

最后,这里有更多关于这些有趣的符号"\\xac\\xed\\x00\\x05t\\x00:"是如何添加到您的 Redis 键的讨论:

  1. Java用奇怪的字符创建Redis键和内容
  2. Spring Boot Redis 将 POJO 列表存储为值
  3. Spring Redis Delete 不删除key

我希望这篇文章可以为您节省一些时间。 快乐编码🔥

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM