Redis(八):spring data redis 理解

前言

Spring Data Redis project,应用了Spring概念来开发使用键值形式的数据存储的解决方案。我们(官方)提供了一个 "template" ,这是一个高级别的抽象,来发送和接收消息。你会注意到它与Spring框架对JDBC的支持有些类似

为什么选择Spring Data Redis?

Spring框架,是引领潮流的全栈Java/JEE应用框架。它提供了一个轻量级容器,一种非侵入式的编程模型 -- 这是由依赖注入、AOP、以及便携的服务抽象开启的。
 
SDR框架,使得利用Redis键值存储非常简单消除了繁复冗余的任务和呆板的代码(指获取连接、释放资源)。

要求

  • SDR 1.x要求JDK 6.0及以上,要求Spring框架4.3.9.RELEASE及以上
  • Redis 2.6.x及以上。在connectors方面,Spring Redis集成了Jedis

连接到Redis

使用Redis和Spring的第一步就是通过IoC容器连接到存储。想要实现连接,一个java connector(或者binding)是必需的。无论选择什么库,都只有一套SDR API,叫做 org.springframework.data.redis.connection package,以及RedisConnectionRedisConnectionFactory接口,来获取到Redis的活动连接。

RedisConnection 和 RedisConnectionFactory

RedisConnection 为Redis通信提供了构建模块,会处理与Redis后端的通信。也会将底层连接库的异常自动翻译成Spring的一致的DAO异常层级,因此,用户能够自由切换connectors,而不必修改代码。

注意:对于需要native库API的情况,RedisConnection提供了专有方法getNativeConnection -- 会返回原生的、底层的用于通信的对象。
活动的RedicConnection由RedisConnectionFactory创建。另外,该工厂还扮演了PersistenceExceptionTranslator,就是说,一旦声明了,它们会允许用户进行透明的异常翻译。例如,通过使用@Repository和AOP的异常翻译。更多信息,见Spring框架的相关部分。
注意:依赖于底层的配置,工厂会返回一个新的连接 或者 一个现有的连接(使用pool或者shared native connection时)。
使用RedisConnectionFactory最简单的方式,是通过IoC容器配置相应的connector,并将其注入使用类中。
重要:不幸的是,目前,不是所有的connector都支持所有的Redis功能。当调用底层库不支持的API时,会抛出UnsupportedOperationException。这种情况在将来可能被解决,视不同的connector的成熟情况。

配置Jedis connector

1.xml配置

<bean id="jedisConnectionFactory" 
               class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"/>

2.java代码配置

@Bean
public JedisConnectionFactory jedisConnectionFactory(){
    return new JedisConnectionFactory();
}

Redis Sentinel支持

为了处理高可用Redis,可以使用RedisSentinelConfiguration来支持Redis Sentinel。

注意:目前,只有Jedis和Lettuce支持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来定义。
  • spring.redis.sentinel.master: master节点的名字
  • spring.redis.sentinel.nodes: 以逗号间隔的host:port列表

有时候,需要直接与Sentinels中的某一个进行交互。使用RedisConnectionFactory.getSentinelConnection() 或者RedisConnection.getSentinelCommands(),可以让你访问第一个活动的Sentinel。

使用RedisTemplate操作Objects

多数用户会喜欢使用RedisTemplate和相应的包org.springframework.data.redis.core,该template是Redis模块的中心类 -- 由于丰富的功能集。该template为Redis交互提供了一个高级别的抽象。当RedisConnection提供了低级别的方法来接受和返还二进制值(byte arrays)时,该template负责了序列化和连接管理,将用户从这里细节中解放了出来。
更多地,该template提供了操作视图(following the grouping from Redis command reference) -- 提供了丰富的接口 来操作特定类型或特定key(通过KeyBound接口),如下:
Table 1. Operational views
InterfaceDescription

Key Type Operations

ValueOperations

Redis string (or value) operations

ListOperations

Redis list operations

SetOperations

Redis set operations

ZSetOperations

Redis zset (or sorted set) operations

HashOperations

Redis hash operations

HyperLogLogOperations

Redis HyperLogLog operations like (pfadd, pfcount,…)

GeoOperations

Redis geospatial operations like GEOADD, GEORADIUS,…)

Key Bound Operations

BoundValueOperations

Redis string (or value) key bound operations

BoundListOperations

Redis list key bound operations

BoundSetOperations

Redis set key bound operations

BoundZSetOperations

Redis zset (or sorted set) key bound operations

BoundHashOperations

Redis hash key bound operations

BoundGeoOperations

Redis key bound geospatial operations.

一旦配置了,该template就是线程安全的,可被多个实例复用。
开箱即用,RedisTemplate使用一个基于Java的序列化器 用于多数操作。这意味着,该template读/写的任意object会通过Java来序列化/反序列化
该template的序列化机制可以轻松地修改,该Redis模块提供了几个实现,在org.springframework.data.redis.serializer包中。你也可以不使用序列化器,直接让RedisTemplate使用原生byte数组,只需要将enableDefaultSerializer设为false即可。
注意,该template要求所有的key都不能是null,但value可以是null -- 只要底层的序列化器接受;更多内容,请查看每个序列化器的javadoc。
当需要一个特定的template view时,将view声明为依赖,并注入该template中即可:容器会自动执行转换:
<bean id="jedisConnectionFactory" 
          class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" 
          p:use-pool="true"/>
    <!-- redis template definition -->
    <bean id="redisTemplate" 
          class="org.springframework.data.redis.core.RedisTemplate"
          p:connection-factory-ref="jedisConnectionFactory"/>
public class Example {
    // inject the actual template
    @Autowired
    private RedisTemplate<String, String> template;
    // inject the template as ListOperations -- 自动转换
    @Resource(name="redisTemplate")
    private ListOperations<String, String> listOps;
    public void addLink(String userId, URL url) {
        listOps.leftPush(userId, url.toExternalForm());
    }
}

聚焦String的便捷类

鉴于使用java.lang.String来作为key/value 存储到Redis中 非常常见,该Redis模块还提供了RedisConnection和RedisTemplate的两个扩展:StringRedisConnection(以及其DefaultStringRedisConnection实现)和StringRedisTemplate。此外,该template和连接,底层使用了StringRedisSerializer

<bean id="jedisConnectionFactory" 
          class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" 
          p:use-pool="true"/>
    <bean id="stringRedisTemplate" 
          class="org.springframework.data.redis.core.StringRedisTemplate" 
          p:connection-factory-ref="jedisConnectionFactory"/>
public class Example {
    @Autowired
    private StringRedisTemplate redisTemplate;
    
    public void addLink(String userId, URL url) {
        redisTemplate.opsForList().leftPush(userId, url.toExternalForm());
    }
}

如同其他的Spring template,RedisTemplate和StringRedisTemplate允许开发者通过RedisCallback接口直接与Redis对话。这赋予了开发者完整的控制,因为是直接与RedisConnection交互。注意,当使用StringRedisTemplate时,该callback接收的是一个StringRedisConnection实例。

public void useCallback() {
    redisTemplate.execute(new RedisCallback<Object>() {
        public Object doInRedis(RedisConnection connection) throws DataAccessException {
            Long size = connection.dbSize();
            // Can cast to StringRedisConnection if using a StringRedisTemplate
            ((StringRedisConnection)connection).set("key", "value");
        }
    });
}

序列化器 Serializers

从框架角度来说,存储在Redis中的数据都是bytes。然而,Redis本身支持不同的类型,更多时候这些是指data存储的方式,而非其表现形式。由用户来决定 信息是否需要转成String或者其他对象。SDR中,用户的类型和原生类型之间的转换,是通过RedisSerializer接口来实现的,如名所示,负责序列化过程。SDR提供了多个开箱即用的实现,其中的两个已经在上面提到了:StringRedisSerializerJdkSerializationRedisSerializer。然而,用户也可以使用OxmSerializer来处理Object/XML映射 -- 通过Spring 3OXM支持;或者,使用JacksonJsonRedisSerializerJackson2JsonRedisSerializer、或者GenericJackson2JsonRedisSerializer 来实现JSON格式的存储。
注意,存储格式不仅限于值,它可以用于键、值、哈希,没有任何限制

Hash映射

Redis中,数据可以使用不同的数据结构来存储。你已经知道 Jackson2JsonRedisSerializer可以将objects转成JSON格式。JSON可以使用字符串来存储。而通过使用Redis Hashes,可以实现一种更复杂的结构化对象的映射。SDR提供了不同的策略来将数据映射成hashes -- 取决于使用情况:
  1. 使用HashOperations和一个序列化器,直接映射。
  2. 使用Redis Repositories。
  3. 使用HashMapper和HashOperations。
posted @ 2018-10-22 20:25  夏威夷8080  阅读(962)  评论(0编辑  收藏  举报