1. 程式人生 > >spring data redis 理解

spring data redis 理解

desc template 開啟 利用 one 反序列化 java代碼 native app

前言

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。

spring data redis 理解