此版本仍在开发中,尚不被认为是稳定的。对于最新的稳定版本,请使用 Spring Data Redis 3.5.3! |
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
.builder(RedisCacheWriter.lockingRedisCacheWriter(connectionFactory))
.cacheDefaults(RedisCacheConfiguration.defaultCacheConfig())
...
默认情况下,任何key
对于缓存条目,以实际缓存名称为前缀,后跟两个冒号(::
).
此行为可以更改为静态前缀和计算前缀。
以下示例演示如何设置静态前缀:
// 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
可能会导致大型关键空间的性能问题。
因此,默认的RedisCacheWriter
可以使用BatchStrategy
切换到SCAN
基于批处理策略。
这SCAN
策略需要批量大小以避免过多的 Redis 命令往返:
RedisCacheManager cacheManager = RedisCacheManager
.builder(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 分钟间隔内只读取了一次,该条目仍将过期。 在声明 TTL 到期策略时,必须编写条目以防止条目过期。
-
空闲时间 (TTI) 过期 - 每当读取条目以及条目更新时,都会重置 TTI,并且是 TTL 过期策略的有效扩展。
某些数据存储在配置 TTL 时使条目过期,无论该条目上发生哪种类型的数据访问作(读取、写入或其他)。 在设置的配置的 TTL 过期超时后,无论如何,该条目都会从数据存储中逐出。 逐出作(例如:销毁、失效、溢出到磁盘(对于持久性存储)等)是特定于数据存储的。 |
生存时间 (TTL) 到期
Spring Data Redis 的Cache
实现支持缓存条目的生存时间 (TTL) 过期。
用户可以将 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 的缓存实现中的 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)
通过调用 Redis 来实现GETEX
命令。
Redis 的 |
为了在 Spring Data Redis 应用程序中实现真正的空闲时间 (TTI) 类似过期的行为,则必须在每次读取或写入作中始终以 (TTL) 过期状态访问条目。此规则没有例外。如果您在 Spring Data Redis 应用程序中混合和匹配不同的数据访问模式(例如:缓存,使用 |