简体   繁体   English

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

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

I want to use Spring cache @Cacheable to manager cache.我想使用 Spring 缓存 @Cacheable 来管理缓存。 And the real cache is redis.而真正的缓存是redis。

my code like that:我的代码是这样的:

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

After I have the post request which is在我收到帖子请求之后

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

the redis server appear a weird key 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"

Spring caching弹簧缓存

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

how to set @Cacheable's Serializer like StringRedisTemplate default:如何设置@Cacheable 的 Serializer 像 StringRedisTemplate 默认值:

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

my application.properties:我的 application.properties:

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

build.gradle构建.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")
}

Create a redis template 创建一个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;
}

Why is it creating a weird string as key? 为什么要创建一个奇怪的字符串作为键?

The key is created based on the argument attributes present in your method which is annotated as cacheable. 密钥是根据方法中存在的参数属性创建的,该属性被注释为可缓存。 This is how spring reads the cache value from redis. 这就是spring从redis读取缓存值的方式。

The caching - feature of Spring allows to use different cache - implementations. Spring的缓存功能允许使用不同的缓存实现。 One of them is Redis. Redis是其中之一。 It can be used with the class RedisCacheManager . 它可以与类RedisCacheManager一起使用。 The Spring documentation says: Spring文档说:

If Redis is available and configured, the RedisCacheManager is auto-configured. 如果Redis可用并已配置,则RedisCacheManager将自动配置。

This is the approach that I propose to influence the Redis - caching - integration: 这是我建议影响Redis(缓存)集成的方法:

  1. Define the RedisCacheManager as bean on your own. 自己将RedisCacheManager定义为bean。

  2. Pass the RedisTemplate to the constructor of RedisCacheManager . RedisTemplate传递给RedisTemplate的构造RedisCacheManager

I found an example for this on the Internet using a programmmatic configuration. 我在Internet上使用编程配置找到了一个示例 There is also an example using XML-based configuration. 还有一个使用基于XML的配置的示例

like mm759's answer: 就像mm759的答案:

  1. Define the RedisCacheManager as bean on your own. 自己将RedisCacheManager定义为bean。

    1. Pass the RedisTemplate to the constructor of RedisCacheManager. 将RedisTemplate传递给RedisCacheManager的构造函数。

this code will solve my problem: 此代码将解决我的问题:

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

}

and the redis store like this: 和redis存储是这样的:

在此处输入图片说明

Here are my two cents.这是我的两分钱。 🪙🏛️ 🪙🏛️

TL;DR TL; 博士
Suppose you are looking for a solution to delete all those weird keys.假设您正在寻找一种解决方案来删除所有这些奇怪的键。 Don't waste time composing a one-line bash solution.不要浪费时间编写单行 bash 解决方案。 This won't work, redis-cli KEYS "user*" | xargs redis-cli DEL这行不通, redis-cli KEYS "user*" | xargs redis-cli DEL redis-cli KEYS "user*" | xargs redis-cli DEL (source: How do I remove keys? ). redis-cli KEYS "user*" | xargs redis-cli DEL (来源: 如何删除密钥? )。 Your keys are in binary format piping them won't produce the expected results.您的密钥是二进制格式的管道,它们不会产生预期的结果。 Extend the functionality of the script that created the keys to delete them as well (Think Python, Java, Go, etc.).扩展创建密钥的脚本的功能以删除它们(Think Python、Java、Go 等)。 Alternatively, delete all keys if you can afford it redis-cli flushall (source: How to atomically delete keys matching a pattern using Redis或者,如果您负担得起,则删除所有键redis-cli flushall (来源: 如何使用 Redis 原子地删除与模式匹配的键

In terms of having your keys as binary data, I am unsure what the benefits are (repeating, binary keys, not data).就将您的密钥作为二进制数据而言,我不确定有什么好处(重复,二进制密钥,而不是数据)。 Since, it might turn out that it's less space-efficient and time-efficient than expected, at least according to these posts, does-storing-plain-text-data-take-up-less-space-than-storing-the-equivalent-mess , are-binary-storage-methods-more-efficient-than-text-based-ones .因为,结果可能证明它的空间效率和时间效率低于预期,至少根据这些帖子, do-storing-plain-text-data-take-up-less-space-than-storing-the-等效混乱are-binary-storage-methods-more-efficient-than-text-based-ones Of course, if you have converted your keys on purpose.当然,如果您有意转换了密钥。

If you wish to have your keys in string format, on the Redis template, set the key serializer as a StringRedisSerializer , as pointed out in the answer by @Rohith K .如果您希望将密钥设为字符串格式,请在 Redis 模板上将密钥序列化器设置为StringRedisSerializer ,如@Rohith K的回答中所指出的。 This would enable you to delete keys by using the pattern matching command quoted above.这将使您能够使用上面引用的模式匹配命令来删除键。

redisTemplate.setKeySerializer(new StringRedisSerializer());

Finally, here are some more discussions about how those funny symbols, "\\xac\\xed\\x00\\x05t\\x00:" , got prepended to your Redis keys:最后,这里有更多关于这些有趣的符号"\\xac\\xed\\x00\\x05t\\x00:"是如何添加到您的 Redis 键的讨论:

  1. Java creating Redis key and content with strange characters Java用奇怪的字符创建Redis键和内容
  2. Spring Boot Redis store a list of POJOs as values Spring Boot Redis 将 POJO 列表存储为值
  3. Spring Redis Delete does not delete key Spring Redis Delete 不删除key

I hope this post saves you some time.我希望这篇文章可以为您节省一些时间。 Happy coding 🔥快乐编码🔥

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

相关问题 java.sql.SQLException:不正确的字符串值:'\xAC\xED\x00\x05sr...' - java.sql.SQLException: Incorrect string value: '\xAC\xED\x00\x05sr...' 无法将字符串 '\xAC\xED\x00\x05~r...' 从二进制转换为 utf8mb3 - Cannot convert string '\xAC\xED\x00\x05~r...' from binary to utf8mb3 这个&#39;\\ x00 \\ x00 \\ x00 \\ x05&#39;的编码是什么? - What encoding is this '\x00\x00\x00\x05'? Hibernate 数据截断:不正确的 integer 值:'\xAC\xED\x00\x05sr\x00&amp; 尝试保存 OneToMany 关系时 - Hibernate data truncation: Incorrect integer value: '\xAC\xED\x00\x05sr\x00& when trying to save a OneToMany Relation 字符串作为\\ x03 \\ x00 \\ x00 \\ x00到整数 - String as \x03\x00\x00\x00 to integer HBase java 错误 - 预期 HEADER=HBas 但收到 HEADER=\x00\x00\x01\x0B - HBase java error - Expected HEADER=HBas but received HEADER=\x00\x00\x01\x0B 在向Accumulo写入文本时尾随空(\\ x00)字符 - Trailing null (\x00) characters when writing text to Accumulo 为什么SqlExceptionHelper将布尔约束违反解释为\\ x00 - Why does SqlExceptionHelper interpret boolean constraint violation as \x00 Java 使用 AsynchronousSocketChannel 将空字节 (\\x00) 作为 1 个字符发送 - Java send nullbyte (\x00) as 1 character using AsynchronousSocketChannel 如何使在x:00 x:15 x:30和x:45上运行的线程在2:00做一些不同的事情 - How to make a thread that runs at x:00 x:15 x:30 and x:45 do something different at 2:00
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM