Redis 缓存
Spring Data Redis 在org.springframework.data.redis.cache包。
要使用 Redis 作为后备实现,请添加RedisCacheManager添加到您的配置中,如下所示:
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
    return RedisCacheManager.create(connectionFactory);
}
RedisCacheManager行为可以通过以下方式配置RedisCacheManager.RedisCacheManagerBuilder,允许您设置默认值RedisCacheManager、事务行为和预定义缓存。
RedisCacheManager cacheManager = RedisCacheManager.builder(connectionFactory)
    .cacheDefaults(RedisCacheConfiguration.defaultCacheConfig())
    .transactionAware()
    .withInitialCacheConfigurations(Collections.singletonMap("predefined",
        RedisCacheConfiguration.defaultCacheConfig().disableCachingNullValues()))
    .build();
如前面的示例所示,RedisCacheManager允许基于每个缓存进行自定义配置。
的行为RedisCache创建者RedisCacheManager定义为RedisCacheConfiguration.
该配置允许您设置密钥过期时间、前缀和RedisSerializer用于与二进制存储格式相互转换的实现,如以下示例所示:
RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
    .entryTtl(Duration.ofSeconds(1))
    .disableCachingNullValues();
RedisCacheManager默认为无锁RedisCacheWriter用于读取和写入二进制值。
无锁缓存可提高吞吐量。
缺少入口锁定可能会导致Cache putIfAbsent和clean作,因为这些作需要向 Redis 发送多个命令。
锁定对应项通过设置显式锁定键并检查是否存在此键来防止命令重叠,这会导致额外的请求和潜在的命令等待时间。
锁定适用于缓存级别,而不是每个缓存条目。
可以按如下方式选择加入锁定行为:
RedisCacheManager cacheManager = RedisCacheManager
    .build(RedisCacheWriter.lockingRedisCacheWriter(connectionFactory))
    .cacheDefaults(RedisCacheConfiguration.defaultCacheConfig())
    ...
默认情况下,任何key,缓存条目以实际缓存名称为前缀,后跟两个冒号 (::).
此行为可以更改为 static 和 computed 前缀。
以下示例显示如何设置静态前缀:
// static key prefix
RedisCacheConfiguration.defaultCacheConfig().prefixCacheNameWith("(͡° ᴥ ͡°)");
The following example shows how to set a computed prefix:
// computed key prefix
RedisCacheConfiguration.defaultCacheConfig()
    .computePrefixWith(cacheName -> "¯\_(ツ)_/¯" + cacheName);
缓存实现默认使用KEYS和DEL以清除缓存。KEYS可能会导致大型 keyspace 的性能问题。
因此,默认的RedisCacheWriter可以使用BatchStrategy切换到SCAN-基于批处理策略。
这SCANstrategy 需要批量大小以避免过多的 Redis 命令往返:
RedisCacheManager cacheManager = RedisCacheManager
    .build(RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory, BatchStrategies.scan(1000)))
    .cacheDefaults(RedisCacheConfiguration.defaultCacheConfig())
    ...
| 
 这  | 
下表列出了RedisCacheManager:
| 设置 | 值 | 
|---|---|
缓存写入器  | 
非锁定 /  | 
缓存配置  | 
  | 
初始缓存  | 
没有  | 
事务感知  | 
不  | 
下表列出了RedisCacheConfiguration:
| 密钥过期 | 没有 | 
|---|---|
缓存  | 
是的  | 
前缀键  | 
是的  | 
默认前缀  | 
实际缓存名称  | 
密钥序列化器  | 
  | 
值序列化器  | 
  | 
转换服务  | 
  | 
| 
 默认情况下  | 
Redis 缓存过期
空闲时间 (TTI) 和生存时间 (TTL) 的实现在定义和行为上各不相同,甚至在不同的数据存储中也是如此。
通常:
- 
生存时间 (TTL) 过期 - TTL 只能通过创建或更新数据访问作来设置和重置。 只要在 TTL 过期超时之前写入条目(包括在创建时),条目的超时就会重置为配置的 TTL 过期超时持续时间。 例如,如果 TTL 过期超时设置为 5 分钟,则超时将在创建条目时设置为 5 分钟,并在此后更新 5 分钟后以及 5 分钟间隔到期之前重置为 5 分钟。 如果 5 分钟内没有更新,即使在 5 分钟的间隔内该条目被读取了多次,甚至只读取了一次,该条目仍然会过期。 必须写入该条目,以防止在声明 TTL 过期策略时该条目过期。
 - 
空闲时间 (TTI) 过期 - 每当读取条目以及条目更新时,都会重置 TTI,并且实际上是 TTL 过期策略的扩展。
 
| 
 配置 TTL 时,某些数据存储会使条目过期,无论条目上发生何种类型的数据访问作(读取、写入或其他作)。 在设置配置的 TTL 过期超时后,无论如何都会从数据存储中逐出该条目。 驱逐作(例如:destroy、invalidate、overflow-to-disk(用于持久存储)等)是特定于数据存储的。  | 
生存时间 (TTL) 过期
Spring Data Redis 的Cacheimplementation 支持缓存条目的生存时间 (TTL) 过期。
用户可以使用固定的Duration或动态计算的Duration通过提供新的RedisCacheWriter.TtlFunction接口。
| 
 这  | 
如果所有缓存条目都应在设定的持续时间后过期,则只需将 TTL 过期超时配置为固定的Duration如下:
RedisCacheConfiguration fiveMinuteTtlExpirationDefaults =
    RedisCacheConfiguration.defaultCacheConfig().enableTtl(Duration.ofMinutes(5));
但是,如果 TTL 过期超时应因缓存条目而异,则必须提供RedisCacheWriter.TtlFunction接口:
enum MyCustomTtlFunction implements TtlFunction {
    INSTANCE;
    @Override
    public Duration getTimeToLive(Object key, @Nullable Object value) {
        // compute a TTL expiration timeout (Duration) based on the cache entry key and/or value
    }
}
| 
 在引擎盖下,一个固定的  | 
然后,您可以配置固定的Duration或动态的、每个缓存的条目Duration使用以下内容在全球范围内实现 TTL 过期:
RedisCacheManager cacheManager = RedisCacheManager.builder(redisConnectionFactory)
    .cacheDefaults(fiveMinuteTtlExpirationDefaults)
    .build();
或者:
RedisCacheConfiguration defaults = RedisCacheConfiguration.defaultCacheConfig()
        .entryTtl(MyCustomTtlFunction.INSTANCE);
RedisCacheManager cacheManager = RedisCacheManager.builder(redisConnectionFactory)
    .cacheDefaults(defaults)
    .build();
当然,您可以使用以下方法组合全局配置和每缓存配置:
RedisCacheConfiguration predefined = RedisCacheConfiguration.defaultCacheConfig()
                                         .entryTtl(MyCustomTtlFunction.INSTANCE);
Map<String, RedisCacheConfiguration> initialCaches = Collections.singletonMap("predefined", predefined);
RedisCacheManager cacheManager = RedisCacheManager.builder(redisConnectionFactory)
    .cacheDefaults(fiveMinuteTtlExpirationDefaults)
    .withInitialCacheConfigurations(initialCaches)
    .build();
空闲时间 (TTI) 过期
Redis 本身不支持真正的空闲时间 (TTI) 过期的概念。 尽管如此,使用 Spring Data Redis 的 Cache 实现,可以实现类似空闲时间 (TTI) 过期的行为。
Spring Data Redis 的 Cache 实现中的 TTI 配置必须显式启用,即选择加入。
此外,您还必须使用固定的Duration或TtlFunction接口,如上文 Redis 缓存过期中所述。
例如:
@Configuration
@EnableCaching
class RedisConfiguration {
    @Bean
    RedisConnectionFactory redisConnectionFactory() {
        // ...
    }
    @Bean
    RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
        RedisCacheConfiguration defaults = RedisCacheConfiguration.defaultCacheConfig()
            .entryTtl(Duration.ofMinutes(5))
            .enableTimeToIdle();
        return RedisCacheManager.builder(connectionFactory)
            .cacheDefaults(defaults)
            .build();
    }
}
由于 Redis 服务器没有实现正确的 TTI 概念,因此只能通过接受过期选项的 Redis 命令来实现 TTI。
在 Redis 中,“过期”在技术上是一种生存时间 (TTL) 策略。
但是,在读取键的值时可以传递 TTL 过期,从而有效地重置 TTL 过期超时,就像现在在 Spring Data Redis 的Cache.get(key)操作。
RedisCache.get(key)通过调用 RedisGETEX命令。
| 
 Redis  | 
| 
 为了在 Spring Data Redis 应用程序中实现真正的空闲时间 (TTI) 过期行为,必须在每次读取或写入作时都使用 (TTL) 过期来一致地访问条目。
此规则没有例外。
如果您在 Spring Data Redis 应用程序中混合和匹配不同的数据访问模式(例如:缓存、使用  |