参考文档: https://docs.spring.io/spring-data/redis/docs/2.0.3.RELEASE/reference/html/html
Redis中文教程: http://www.redis.net.cn/tutorial/3501.htmljava
Redis官方中文文档之Redis集群教程: http://ifeve.com/redis-cluster-tutorial/node
本文是从5.3.1. RedisConnection and RedisConnectionFactory 开始翻译的,由于前面的章节不太实用。react
点击下面的连接可直达官网:git
RedisConnectionFactory: 用于建立RedisConnection 实例,根据底层配置,RedisConnectionFactory 能够返回一个新链接或现有链接(以防止链接池或共享的本地链接已经使用),使用RedisConnectionFactory的最简单方法是经过IoC容器配置适当的链接器(链接器:connector;Jekis就是其中一种链接器),并将其注入到使用的类中。不幸的是,目前并不是全部链接器都支持全部Redis功能。当调用链接的方法是底层API库不受支持的方法时,一个UnsupportedOperationException将会被抛出。 随着各类链接器的成熟,这种状况在将来可能会获得解决。github
Jedis是Spring Data Redis模块经过org.springframework.data.redis.connection.jedis包支持的链接器之一。 最简单形式的Jedis配置以下所示:redis
可是,对于生产环境(Production)用途,可能须要调整主机或密码等设置:p:host-name="server" p:port="6379"spring
Lettuce是一个Spring Data Redis经过org.springframework.data.redis.connection.lettuce包支持的基于netty的可伸缩线程安全的开源链接器(Redis客户端)。多个线程能够共享同一个RedisConnection。它利用优秀netty NIO框架来高效地管理多个链接。Lettuce 的详细介绍和下载地址:点击下载sql
配置方式与Jedis相似:编程
还有一些能够调整的Lettuce专用的链接参数。 默认状况下,由LettuceConnectionFactory建立的全部LettuceConnection共享用于全部非阻塞和非事务操做的相同线程安全本机链接。 将shareNativeConnection设置为false,以便每次都使用专用链接。 LettuceConnectionFactory也能够配置为使用LettucePool来共享阻塞和事务链接,或者若是shareNativeConnection设置为false,则可使用全部链接。
为了处理高可用性的Redis,RedisSentinel使用RedisSentinelConfiguration支持Redis Sentinel
/** * jedis */ @Bean public RedisConnectionFactory jedisConnectionFactory() { RedisSentinelConfiguration sentinelConfig = new RedisSentinelConfiguration() .master("mymaster") .sentinel("127.0.0.1", 26379) .sentinel("127.0.0.1", 26380); return new JedisConnectionFactory(sentinelConfig); } /** * Lettuce */ @Bean public RedisConnectionFactory lettuceConnectionFactory() { RedisSentinelConfiguration sentinelConfig = new RedisSentinelConfiguration() .master("mymaster") .sentinel("127.0.0.1", 26379) .sentinel("127.0.0.1", 26380); return new LettuceConnectionFactory(sentinelConfig); }RedisSentinelConfiguration也能够经过PropertySource(在applicatoin.properties或者其余在classpath上的properties)定义。
如下是一个使用Lua脚本执行常见“检查并设置”场景的示例。对于Redis脚原本说,这是一个理想的用例,由于它要求咱们以原子方式执行一组命令,而且一个命令的行为受另外一个命令的影响。
@Bean public RedisScript<Boolean> script() { ScriptSource scriptSource = new ResourceScriptSource(new ClassPathResource("META-INF/scripts/checkandset.lua"); return RedisScript.of(scriptSource, Boolean.class); }
public class Example { @Autowired RedisScript<Boolean> script; public boolean checkAndSet(String expectedValue, String newValue) { return redisTemplate.execute(script, singletonList("key"), asList(expectedValue, newValue)); } }
-- checkandset.lua local current = redis.call('GET', KEYS[1]) if current == ARGV[1] then redis.call('SET', KEYS[1], ARGV[2]) return true end return false上面的代码配置RedisScript指向名为checkandset.lua的文件,该文件预计会返回一个布尔值。脚本resultType应该是Long,Boolean,List或反序列化值类型之一。 若是脚本返回丢弃状态(即“OK”),它也能够为空。 在应用程序上下文中配置DefaultRedisScript的单个实例是很是理想的,以免在每次脚本执行时从新计算脚本的SHA1。
Package org.springframework.data.redis.support提供各类可重用组件,这些组件依赖Redis做为后备存储。目前,该软件包在Redis之上包含各类基于JDK的界面实现,如原子计数器和JDK集合。
原子计数器能够轻松地包装Redis密钥增量,而集合容许以最小的存储空间或API泄漏轻松管理Redis密钥:特别是RedisSet和RedisZSet接口能够轻松访问Redis支持的集合操做,例如交集intersection
和联合union
,而RedisList在Redis之上实现了List,Queue和Deque契约(及其等效的同级同胞),将存储做为FIFO(先进先出),LIFO(后进先出)或采用最小配置的集合:
public class AnotherExample { // injected private Deque<String> queue; public void addTag(String tag) { queue.push(tag); } }
如上例所示,使用代码与实际的存储实现分离 - 事实上,没有指出在下面使用Redis的状况。 这使得从开发到生产环境变得透明而且极大地提升了可测试性(Redis实现能够被在内存中的一个所取代)。
@Bean public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) { return RedisCacheManager.create(connectionFactory); }
RedisCacheManager行为能够经过RedisCacheManagerBuilder配置,容许设置默认的RedisCacheConfiguration,事务行为和预约义的缓存。
RedisCacheManager cm = RedisCacheManager.builder(connectionFactory) .cacheDefaults(defaultCacheConfig()) .initialCacheConfigurations(singletonMap("predefined", defaultCacheConfig().disableCachingNullValues())) .transactionAware() .build();
经过RedisCacheManager建立的RedisCache的行为经过RedisCacheConfiguration定义。该配置容许设置密钥到期时间,前缀和RedisSerializer以转换为二进制存储格式和从二进制存储格式转换。 如上所示,RedisCacheManager容许定义每一个缓存库上的配置。
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofSeconds(1)) .disableCachingNullValues();
RedisCacheManager默认使用无锁 Lock-free RedisCacheWriter来读取和写入二进制值。无锁缓存提升了吞吐量。 缺乏入口锁定可能会致使putIfAbsent和clean方法的重叠非原子命令,由于那些方法须要将多个命令发送到Redis。 锁定副本经过设置显式锁定键explicit lock key并检查是否存在此键来防止命令重叠,这会致使额外的请求和潜在的命令等待时间。
能够选择加入锁定行为以下:
RedisCacheManager cm = RedisCacheManager.build(RedisCacheWriter.lockingRedisCacheWriter()) .cacheDefaults(defaultCacheConfig()) ...
Table 4. RedisCacheManager defaults
Table 5. RedisCacheConfiguration defaults
6. Reactive Redis support
本节介绍Redis支持以及如何入门。 你会发现与imperative Redis support有某些重叠。
Spring Data Redis须要Redis 2.6或更高版本以及Java SE 8.0或更高版本。 在语言绑定(或链接器)方面,Spring Data Redis目前与Lettuce集成为惟一的reactive Java链接器。 Project Reactor被做为reactive组合库。
Redis能够做为独立服务器运行,使用Redis Sentinel或Redis Cluster模式运行。 Lettuce
支持上面提到的全部链接类型。
根据底层配置,工厂能够返回新链接或现有链接(若是使用池或共享本地链接)。
使用Reactive RedisConnectionFactory的最简单方法是经过IoC容器配置适当的链接器,并将其注入到使用的类中。
@Bean public ReactiveRedisConnectionFactory connectionFactory() { return new LettuceConnectionFactory("localhost", 6379); }
使用LettuceClientConfigurationBuilder的更复杂的配置(包括SSL和超时)以下所示:
@Bean public ReactiveRedisConnectionFactory lettuceConnectionFactory() { LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder() .useSsl().and() .commandTimeout(Duration.ofSeconds(2)) .shutdownTimeout(Duration.ZERO) .build(); return new LettuceConnectionFactory(new RedisStandaloneConfiguration("localhost", 6379), clientConfig); }
有关更详细的客户端配置调整,请参阅LettuceClientConfiguration。
Most users are likely to use ReactiveRedisTemplate
and its corresponding package org.springframework.data.redis.core
- the template is in fact the central class of the Redis module due to its rich feature set. The template offers a high-level abstraction for Redis interactions. While ReactiveRedisConnection
offers low level methods that accept and return binary values (ByteBuffer
), the template takes care of serialization and connection management, freeing the user from dealing with such details.
Moreover, the template provides operation views (following the grouping from Redis command reference) that offer rich, generified interfaces for working against a certain type as described below:
Table 6. Operational views
配置完成后,该模板是线程安全的,能够在多个实例中重复使用。
开箱即用,ReactiveRedisTemplate在其大部分操做中使用基于Java的序列化程序。 这意味着模板写入或读取的任何对象都将经过RedisElementWriter和RedisElementReader进行序列化/反序列化。序列化上下文在构建时传递给模板,Redis模块在org.springframework.data.redis.serializer包中提供了几个可用实现 - 请参阅序列化程序以获取更多信息。
@Configuration class RedisConfiguration { @Bean ReactiveRedisTemplate<String, String> reactiveRedisTemplate(ReactiveRedisConnectionFactory factory) { return new ReactiveRedisTemplate<>(connectionFactory, RedisSerializationContext.string()); } }
public class Example { @Autowired private ReactiveRedisTemplate<String, String> template; public Mono<Long> addLink(String userId, URL url) { return template.opsForList().leftPush(userId, url.toExternalForm()); } }
经过ReactiveRedisTemplate使用ReactiveScriptExecutor也能够实现Reactive基础构建执行 Redis scripts的功能。
public class Example { @Autowired private ReactiveRedisTemplate<String, String> template; public Flux<Long> theAnswerToLife() { DefaultRedisScript<Long> script = new DefaultRedisScript<>(); script.setLocation(new ClassPathResource("META-INF/scripts/42.lua")); script.setResultType(Long.class); return reactiveTemplate.execute(script); } }
使用Redis群集Redis Cluster须要Redis Server 3.0+版本,并提供了一套本身的特性和功能。 有关更多信息,请参阅群集教程Cluster Tutorial。
@Component @ConfigurationProperties(prefix = "spring.redis.cluster") public class ClusterConfigurationProperties { /* * spring.redis.cluster.nodes[0] = 127.0.0.1:7379 * spring.redis.cluster.nodes[1] = 127.0.0.1:7380 * ... */ List<String> nodes; /** * Get initial collection of known cluster nodes in format {@code host:port}. * * @return */ public List<String> getNodes() { return nodes; } public void setNodes(List<String> nodes) { this.nodes = nodes; } } @Configuration public class AppConfig { /** * Type safe representation of application.properties */ @Autowired ClusterConfigurationProperties clusterProperties; public @Bean RedisConnectionFactory connectionFactory() { return new JedisConnectionFactory( new RedisClusterConfiguration(clusterProperties.getNodes())); } }
RedisClusterConfiguration
能够经过 PropertySource
定义
spring.redis.cluster.nodes
: 逗号分隔host:port
spring.redis.cluster.max-redirects
: 容许cluster重定向的数量
初始配置将驱动程序库指向初始集群节点集。 活动群集从新配置所产生的更改只会保留在本机驱动程序中,而不会写回配置。
尽管重定向到相应的插槽服务节点的特定密钥由驱动程序库处理,但高级函数(如收集跨节点的信息)或将命令发送到群集中由RedisClusterConnection覆盖的全部节点。从上面的例子中,咱们能够看到,当获取结果和返回的一组键值时,key(pattern)方法获取集群中的每一个主节点,并同时对每一个主节点执行KEYS命令。仅仅请求单个节点的密钥,RedisClusterConnection为那些(如密钥(节点,模式))提供重载。
RedisClusterNode能够从RedisClusterConnection.clusterGetNodes得到,也可使用主机和端口或节点ID构建。
Example 2. Sample of Running Commands Across the Cluster
当全部密钥映射到同一个插槽时,本地驱动程序库会自动为跨插槽请求(如MGET)提供服务。可是,一旦状况并不是如此,RedisClusterConnection将针对插槽服务节点执行多个并行GET命令,并再次返回累计结果。显然,这比单个插槽执行的性能差,所以应该当心使用。 若有疑问,请在{my-prefix} .foo和{my-prefix} .bar这样的大括号中提供一个前缀,将它们映射到相同的插槽编号,从而考虑将密钥固定到同一个插槽。
Example 3. Sample of Cross Slot Request Handling
以上提供了简单的例子来演示Spring Data Redis遵循的通常策略。 请注意,某些操做可能须要将大量数据加载到内存中才能计算所需的命令。此外,并不是全部的交叉插槽请求均可以安全地移植到多个单插槽请求中,而且若是使用不当(例如PFCOUNT),则会出错。
RedisTemplate的通常用途请参阅5.5: http://blog.csdn.net/michaelehome/article/details/79485661
使用任何JSON-RedisSerializer设置RedisTemplate#keySerializer时请当心,由于更改json结构会对散列槽计算产生直接影响。
RedisTemplate可经过RedisTemplate.opsForCluster()获取的ClusterOperations接口提供对集群特定操做的访问。 这容许在集群内的单个节点上明确执行命令,同时保留为模板配置的解除/序列化功能,并提供管理命令,例如CLUSTER MEET或更高级别的操做。resharding。
Example 4. Accessing RedisClusterConnection via RedisTemplate
Redis存储库至少须要Redis Server 2.8.0版。
Example 5. Sample Person Entity
@RedisHash("persons") public class Person { @Id String id; String firstname; String lastname; Address address; }
咱们在这里有一个很是简单的域对象domain object。请注意,它有一个名为id的属性,其中注明了org.springframework.data.annotation.Id和一个类型为@RedisHash的注解。这两个负责建立用于保存散列的实际密钥。用@Id注释的属性以及那些名为id的属性被视为标识符属性。 那些带有注释的比其余的更受青睐。
如今实际上有一个负责存储storage和检索retrieval的组件,咱们须要定义一个存储库接口repository interface。
Example 6. Basic Repository Interface To Persist Person Entities
public interface PersonRepository extends CrudRepository<Person, String> { }
因为咱们的repository 扩展了CrudRepository,它提供了基本的CRUD和查找操做。 咱们须要将二者粘合在一块儿的是Spring配置。
Example 7. JavaConfig for Redis Repositories
@Configuration @EnableRedisRepositories public class ApplicationConfig { @Bean public RedisConnectionFactory connectionFactory() { return new JedisConnectionFactory(); } @Bean public RedisTemplate<?, ?> redisTemplate() { RedisTemplate<byte[], byte[]> template = new RedisTemplate<byte[], byte[]>(); return template; } }
鉴于上面的设置,咱们能够继续并将PersonRepository注入到组件中。
Example 8. Access to Person Entities
1. 若是当前值为null,则生成一个新的ID,或重用一个id,而后设置id的值,将Key和keyspace:id,还有Person类型的属性一块儿存储到Redis Hash中。对于这种状况,例如: persons:5d67b7e1-8640-4475-BEEB-c666fab4c0e5。
2. 使用提供的ID检索存储在keyspace:id处的对象。
3. 经过在Person上使用@RedisHash计算keyspace persons中的全部可用实体的总数。
4. 从Redis中删除给定对象的键。
基于前面几节中的Person类型,默认映射以下所示:
1. _class属性包含在根级别以及任何嵌套的接口或抽象类型中。
2. 简单的属性值是经过路径被映射的。
3. 复杂类型的属性由它们的点路径映射。
Table 7. Default Mapping Rules
Mapping behavior can be customized by registering the according Converter
in RedisCustomConversions
. Those converters can take care of converting from/to a single byte[]
as well as Map<String,byte[]>
whereas the first one is suitable for eg. converting one complex type to eg. a binary JSON representation that still uses the default mappings hash structure. The second option offers full control over the resulting hash. Writing objects to a Redis hash will delete the content from the hash and re-create the whole hash, so not mapped data will be lost.
映射行为能够经过在RedisCustomConversions中注册相应的Converter来定制。这些转换器能够处理单个字节byte[]以及Map <String,byte[]>的转换,而第一个转换器是合适的,例如,转换一种复杂类型,例如,一个二进制JSON表示仍然使用默认映射哈希结构。 第二个选项提供了对返回的Hash的彻底控制。将对象写入Redis Hash将从哈希中删除内容并从新建立整个哈希,所以未映射的数据将丢失。
Example 9. Sample byte[] Converters
@WritingConverter public class AddressToBytesConverter implements Converter<Address, byte[]> { private final Jackson2JsonRedisSerializer<Address> serializer; public AddressToBytesConverter() { serializer = new Jackson2JsonRedisSerializer<Address>(Address.class); serializer.setObjectMapper(new ObjectMapper()); } @Override public byte[] convert(Address value) { return serializer.serialize(value); } } @ReadingConverter public class BytesToAddressConverter implements Converter<byte[], Address> { private final Jackson2JsonRedisSerializer<Address> serializer; public BytesToAddressConverter() { serializer = new Jackson2JsonRedisSerializer<Address>(Address.class); serializer.setObjectMapper(new ObjectMapper()); } @Override public Address convert(byte[] value) { return serializer.deserialize(value); } }
使用上述byte[] Converter
产生的例子:
_class = org.example.Person id = e2c7dcee-b8cd-4424-883e-736ce564363e firstname = rand lastname = al’thor address = { city : "emond's field", country : "andor" }
Example 10. Sample Map<String,byte[]> Converters
@WritingConverter public class AddressToMapConverter implements Converter<Address, Map<String,byte[]>> { @Override public Map<String,byte[]> convert(Address source) { return singletonMap("ciudad", source.getCity().getBytes()); } } @ReadingConverter public class MapToAddressConverter implements Converter<Address, Map<String, byte[]>> { @Override public Address convert(Map<String,byte[]> source) { return new Address(new String(source.get("ciudad"))); } }
用上述的Map Converter
产生的例子:
_class = org.example.Person id = e2c7dcee-b8cd-4424-883e-736ce564363e firstname = rand lastname = al’thor ciudad = "emond's field"自定义转换对索引的定义没有任何影响。 即便对于自定义转换类型,二级索引也将会被建立。
getClass().getName()
. This default can be altered via
@RedisHash
on aggregate root level or by setting up a programmatic configuration. However, the annotated keyspace supersedes any other configuration.
Keyspaces定义了用于为Redis Hash建立实际Key的前缀。 默认状况下,前缀设置为getClass().getName()。 这个默认值能够经过在类上使用@RedisHash或经过设置程序的配置来改变。 可是,带注解的keyspace将取代任何其余配置。
Example 11. Keyspace Setup via @EnableRedisRepositories
@Configuration @EnableRedisRepositories(keyspaceConfiguration = MyKeyspaceConfiguration.class) public class ApplicationConfig { //... RedisConnectionFactory and RedisTemplate Bean definitions omitted public static class MyKeyspaceConfiguration extends KeyspaceConfiguration { @Override protected Iterable<KeyspaceSettings> initialConfiguration() { return Collections.singleton(new KeyspaceSettings(Person.class, "persons")); } } }
Example 12. Programmatic Keyspace setup
@Configuration @EnableRedisRepositories public class ApplicationConfig { //... RedisConnectionFactory and RedisTemplate Bean definitions omitted @Bean public RedisMappingContext keyValueMappingContext() { return new RedisMappingContext( new MappingConfiguration( new MyKeyspaceConfiguration(), new IndexConfiguration())); } public static class MyKeyspaceConfiguration extends KeyspaceConfiguration { @Override protected Iterable<KeyspaceSettings> initialConfiguration() { return Collections.singleton(new KeyspaceSettings(Person.class, "persons")); } } }
二级索引用于启用基于本机Redis结构的查找操做。 值在每次保存时写入相应的索引,并在对象被删除或过时时被删除。
Example 13. Annotation driven indexing
@RedisHash("persons") public class Person { @Id String id; @Indexed String firstname; String lastname; Address address; }
索引是为实际属性值构建的。 保存两个Persons,例如。 “rand”和“aviendha”将会设置以下的索引。
SADD persons:firstname:rand e2c7dcee-b8cd-4424-883e-736ce564363e SADD persons:firstname:aviendha a9d4b3a0-50d3-4538-a2fc-f7fc2581ee56
在嵌套元素上也能够有索引。 假设地址具备用@Indexed注释的城市属性。 在那种状况下,一旦person.address.city不为空,咱们就为每一个城市设置了Sets。
SADD persons:address.city:tear e2c7dcee-b8cd-4424-883e-736ce564363e
此外,编程设置容许在map keys和list属性上定义索引。
Same as with keyspaces it is possible to configure indexes without the need of annotating the actual domain type.
与keyspaces相同,能够配置索引而不须要在实际的域类型上使用注解。
Example 14. Index Setup via @EnableRedisRepositories
@Configuration @EnableRedisRepositories(indexConfiguration = MyIndexConfiguration.class) public class ApplicationConfig { //... RedisConnectionFactory and RedisTemplate Bean definitions omitted public static class MyIndexConfiguration extends IndexConfiguration { @Override protected Iterable<IndexDefinition> initialConfiguration() { return Collections.singleton(new SimpleIndexDefinition("persons", "firstname")); } } }
Example 15. Programmatic Index setup
@Configuration @EnableRedisRepositories public class ApplicationConfig { //... RedisConnectionFactory and RedisTemplate Bean definitions omitted @Bean public RedisMappingContext keyValueMappingContext() { return new RedisMappingContext( new MappingConfiguration( new KeyspaceConfiguration(), new MyIndexConfiguration())); } public static class MyIndexConfiguration extends IndexConfiguration { @Override protected Iterable<IndexDefinition> initialConfiguration() { return Collections.singleton(new SimpleIndexDefinition("persons", "firstname")); } } }
Address
类型包含一个类型为Point的location属性,该位置保存特定地址的地理坐标。 经过使用@GeoIndexed注解属性,将使用Redis GEO命令添加这些值。
在上面的例子中,使用GEOADD和对象id做为成员的名字来存储lon / lat值。 查找方法容许使用Circle
或 Point, Distance
组合来查询这些值。
不能将near/within与其余标准组合在一块儿。
Example 16. Expirations
public class TimeToLiveOnProperty { @Id private String id; @TimeToLive private Long expiration; } public class TimeToLiveOnMethod { @Id private String id; @TimeToLive public long getTimeToLive() { return new Random().nextLong(); } }使用@TimeToLive显式注释属性将从Redis回读实际的TTL或PTTL值。 -1表示该对象没有过时关联。
repository的实现确保了经过RedisMessageListenerContainer订阅Redis keyspace notifications。
当到期被设置为正值时,执行相应的EXPIRE命令。除了保留原始文件外,仿真副本被存储在Redis中并设置为在原始文件保留5分钟后到期。这样作的目的在于,开启Repository支持,经过Springs ApplicationEventPublisher发布RedisKeyExpiredEvent持有的过时值(当密钥过时甚至原始值已经消失)。全部链接的应用程序将使用Spring Data Redis repository接收到RedisKeyExpiredEvent。
默认状况下,初始化应用程序时,key expiry listener是被禁用的。能够在@EnableRedisRepositories或RedisKeyValueAdapter中调整为启用模式,以启动应用程序的listener,或者在第一次插入具备TTL的实体时自动启动listener。可用的值请参阅EnableKeyspaceEvents。
RedisKeyExpiredEvent将保存实际过时的域对象以及密钥的副本。
延迟或禁用到期事件侦听器启动会影响RedisKeyExpiredEvent发布。 被禁用的事件侦听器不会发布到期事件。 因为延迟侦听器初始化,延迟启动可能致使事件丢失。
keyspace通知消息侦听器将在Redis中更改notify-keyspace-events设置(若是还没有设置这些设置)。 现有的设置不会被覆盖,因此留给用户去正确的设置这些,当现有的设置不为空时。 请注意,在AWS ElastiCache上禁用了CONFIG,启用监听器将致使错误。
Redis Pub / Sub消息不是持久的。 若是在应用程序关闭期间某个键过时,则不会处理到期事件,这可能会致使secondary indexes引用已过时的对象。
使用@Reference标记属性容许存储简单的键引用,而不是将值复制到Hash自己。 在从Redis加载时,引用会自动解析并映射回对象。
Example 17. Sample Property Reference
_class = org.example.Person id = e2c7dcee-b8cd-4424-883e-736ce564363e firstname = rand lastname = al’thor mother = persons:a9d4b3a0-50d3-4538-a2fc-f7fc2581ee56 (1)(1)这个引用存储了被引用对象的整个键(keyspace:id)。
在保存引用对象时,引用对象不会保留更改。 请确保分开保存对引用对象的更改,由于只有引用将被存储。 在引用类型的属性上设置的索引不会被解析。
在某些状况下,不须要加载和重写整个实体,只需在其中设置一个新值便可。 上次活动时间的会话时间戳多是您只想更改一个属性的场景。 PartialUpdate容许定义对现有对象的设置和删除操做,同时负责更新实体自己的潜在到期时间以及索引结构。
PartialUpdate<Person> update = new PartialUpdate<Person>("e2c7dcee", Person.class) .set("firstname", "mat") .set("address.city", "emond's field") .del("age"); template.update(update); update = new PartialUpdate<Person>("e2c7dcee", Person.class) .set("address", new Address("caemlyn", "andor")) .set("attributes", singletonMap("eye-color", "grey")); template.update(update); update = new PartialUpdate<Person>("e2c7dcee", Person.class) .refreshTtl(true); .set("expiration", 1000); template.update(update);
1. Set the simple property firstname to mat. 2. Set the simple property address.city to emond’s field without having to pass in the entire object. This does not work when a custom conversion is registered. 3. Remove the property age. 4. Set complex property address. 5. Set a map/collection of values removes the previously existing map/collection and replaces the values with the given ones. 6. Automatically update the server expiration time when altering Time To Live.
更新复杂对象以及映射/集合结构须要与Redis进一步交互以肯定现有值,这意味着可能会发现重写整个实体可能会更快。
Example 19. Sample Repository finder Method
public interface PersonRepository extends CrudRepository<Person, String> { List<Person> findByFirstname(String firstname); }请确保在查找器方法中使用的属性设置为索引。
Redis存储库的查询方法仅支持查询具备分页的实体和实体集合。
使用派生查询derived query 方法可能并不老是足以对要执行的查询建模。 RedisCallback提供了对索引结构的实际匹配或甚至自定义添加的更多控制。 它所须要的就是提供一个RedisCallback,它返回一个单独的或一组Iterable set的id值。
Example 20. Sample finder using RedisCallback
String user = //... List<RedisSession> sessionsByUser = template.find(new RedisCallback<Set<byte[]>>() { public Set<byte[]> doInRedis(RedisConnection connection) throws DataAccessException { return connection .sMembers("sessions:securityContext.authentication.principal.username:" + user); }}, RedisSession.class);
如下概述了Redis支持的关键字以及包含该关键字的方法。
当全部相关密钥映射到同一个插槽时,只能在服务器端处理像SINTER和SUNION这样的一些命令。 不然,计算必须在客户端完成。 所以将密钥空间keyspaces 固定到单个插槽slot,能够当即使用Redis服务器计算。
在使用Redis群集时,经过`@RedisHash(“{yourkeyspace}”)定义和固定密钥空间到特定的插槽。
Instances of the repository interfaces are usually created by a container, which Spring is the most natural choice when working with Spring Data. There’s sophisticated support to easily set up Spring to create bean instances. Spring Data Redis ships with a custom CDI extension that allows using the repository abstraction in CDI environments. The extension is part of the JAR so all you need to do to activate it is dropping the Spring Data Redis JAR into your classpath.
You can now set up the infrastructure by implementing a CDI Producer for the RedisConnectionFactory
and RedisOperations
:
class RedisOperationsProducer { @Produces RedisConnectionFactory redisConnectionFactory() { JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(new RedisStandaloneConfiguration()); jedisConnectionFactory.afterPropertiesSet(); return jedisConnectionFactory; } void disposeRedisConnectionFactory(@Disposes RedisConnectionFactory redisConnectionFactory) throws Exception { if (redisConnectionFactory instanceof DisposableBean) { ((DisposableBean) redisConnectionFactory).destroy(); } } @Produces @ApplicationScoped RedisOperations<byte[], byte[]> redisOperationsProducer(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<byte[], byte[]> template = new RedisTemplate<byte[], byte[]>(); template.setConnectionFactory(redisConnectionFactory); template.afterPropertiesSet(); return template; } }必要的设置可能因您运行的JavaEE环境而异。
class RepositoryClient { @Inject PersonRepository repository; public void businessMethod() { List<Person> people = repository.findAll(); } }Redis存储库须要RedisKeyValueAdapter和RedisKeyValueTemplate实例。 若是未找到提供的bean,则这些bean由Spring Data CDI扩展建立和管理。 可是,您能够提供本身的Bean来配置RedisKeyValueAdapter和RedisKeyValueTemplate的特定属性。