【问题标题】:How to configure Spring Redis Configuration to use Hash instead of string serialization如何配置 Spring Redis 配置以使用 Hash 而不是字符串序列化
【发布时间】:2020-02-04 08:03:33
【问题描述】:

对于 Java POJO,我想使用 Spring 的 @Cacheable、@CachePut 和 @CacheEvict 将其缓存到 Redis,但是我更喜欢使用 Redis 的 Hash 功能,而不是仅仅将 POJO 序列化为字符串。本质上,我希望能够对 POJO 使用 ObjectHashMapper 之类的东西,以便 POJO 属性自动保存为单个 Redis 条目中的键/值对。这种行为可以在使用 ObjectHashMapper 保存 POJO 的 RedisRepository 功能中看到,但是,我不想将缓存定义为 Repository,而是我想使用 Cache 注释。

我已经成功创建了一些自定义 Spring/Redis 配置,帮助我使字符串序列化正常工作。用于自定义 CacheManager 和 CacheConfiguration 的 Spring 文档非常“轻便”,我没有找到任何相关示例。我不确定是否需要自定义序列化程序、转换器或 CacheConfiguration 的其他方面。似乎序列化程序更关心单个键和值,但我看不到在哪里配置以捕获整个对象并首先将其转换为哈希。

这是我的 Redis 配置。它是为两个缓存“v”和“products”设置的,另外默认为其他缓存的 StringRedisSerializer。

@Slf4j
@RequiredArgsConstructor
@Configuration
@EnableRedisRepositories(enableKeyspaceEvents=RedisKeyValueAdapter.EnableKeyspaceEvents.ON_STARTUP)
public class RedisConfig {

    private final RedisConnectionFactory connectionFactory;

    private static RedisCacheConfiguration createCacheConfiguration(long timeoutInSeconds, RedisSerializationContext.SerializationPair<?> serializationPair) {
        logger.info("Creating CacheConfiguration with timeout of {} seconds", timeoutInSeconds);
        return RedisCacheConfiguration.defaultCacheConfig()
                .serializeValuesWith(serializationPair)
                .entryTtl(Duration.ofSeconds(timeoutInSeconds));
    }

    @Bean
    public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
        logger.info("Creating cache manager");
        Map<String, RedisCacheConfiguration> cacheConfigurations = new HashMap<>();

        cacheConfigurations.put("v",createCacheConfiguration(1200, RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())));
        cacheConfigurations.put("products",createCacheConfiguration(-1,RedisSerializationContext.SerializationPair.fromSerializer(new JdkSerializationRedisSerializer())));

        return RedisCacheManager
                .builder(connectionFactory)
                .cacheDefaults(createCacheConfiguration(-1,RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())))
                .withInitialCacheConfigurations(cacheConfigurations)
                .build();
    }
}

这是一个 POJO 如何按照上述配置序列化的示例:

@Data
@Builder
@AllArgsConstructor
public class ProductSummary implements Serializable {
    @Id
    private String id;
    private String accountId;
    private String name;
    private String roles;
    private String groups;
}

以及它的序列化方式:

\xac\xed\x00\x05sr\x004com.foobar.ProductSummaryh\xb3\x9d
\xd4\x0f\xac\xea\xb3\x02\x00\x05L\x00\taccountIdt\x00
\x12Ljava/lang/String;L\x00\x06groupsq\x00~\x00\x01L\x00
\x02idq\x00~\x00\x01L\x00\x04nameq\x00~\x00\x01L\x00
\x05rolesq\x00~\x00\x01xpt\x00\x19acctFv825MKt\x00
\nimwebuserst\x00\x13prod0lwJAWEYt\x00\x11ProductName/2020t\x00\x00

我想要的是(在 Redis 中作为哈希):

>HGETALL KEY

 1) "_class"
 2) "com.foobar.cache.CheckoutState"
 3) "accountId"
 4) "ACC000001"
 5) "name"
 6) "lorem ipsum whatever"
 7) "roles"
 8) "role1,role2,role3"
 9) "groups"
10) "groupA,groupB"

哈希键为 id。

【问题讨论】:

  • 您找到解决方案了吗?

标签: caching serialization hashmap pojo spring-data-redis


【解决方案1】:

猜猜这不再那么重要了,但也许其他人也想做同样的事情,比如我。

这并不容易,因为在实现的深处 DefaultRedisCacheWriter

使用“SET” - 您基本上想要的是 connection.hSet。在我看来,实现这一目标的唯一方法是实现自己的 RedisCacheWriter

这可能还不够,因为接口定义:

redis缓存管理器调用:

长话短说,我假设一个自己的“RedisCache”缓存类可能是最简单的方法,只使用一个简单的 spring data redis“HASH”类,或者使用 RedisTemplate 更简单一些结合 spring ObjectHashMapper 来创建这些哈希。

【讨论】:

    猜你喜欢
    • 2020-10-01
    • 2013-07-07
    • 2020-09-11
    • 1970-01-01
    • 2019-07-31
    • 1970-01-01
    • 1970-01-01
    • 2014-07-30
    • 1970-01-01
    相关资源
    最近更新 更多