Spring-data-redis:特性與實例--轉載

原文地址:http://shift-alt-ctrl.iteye.com/blog/1886831java

Spring-data-redis爲spring-data模塊中對redis的支持部分,簡稱爲「SDR」,提供了基於jedis客戶端API的高度封裝以及與spring容器的整合,事實上jedis客戶端已經足夠簡單和輕量級,而spring-data-redis反而具備「過分設計」的嫌疑。redis

    jedis客戶端在編程實施方面存在以下不足:spring

    1) connection管理缺少自動化,connection-pool的設計缺乏必要的容器支持。apache

    2) 數據操做須要關注「序列化」/「反序列化」,由於jedis的客戶端API接受的數據類型爲string和byte,對結構化數據(json,xml,pojo等)操做須要額外的支持。編程

    3) 事務操做純粹爲硬編碼json

    4) pub/sub功能,缺少必要的設計模式支持,對於開發者而言須要關注的太多。設計模式

    不過jedis與spring整合,也是很是的簡單,參見「jedis鏈接池實例」.api

 

一.  spring-data-redis針對jedis提供了以下功能架構

    1. 鏈接池自動管理,提供了一個高度封裝的「RedisTemplate」類app

    2. 針對jedis客戶端中大量api進行了歸類封裝,將同一類型操做封裝爲operation接口

  • ValueOperations:簡單K-V操做
  • SetOperations:set類型數據操做
  • ZSetOperations:zset類型數據操做
  • HashOperations:針對map類型的數據操做
  • ListOperations:針對list類型的數據操做

    3. 提供了對key的「bound」(綁定)便捷化操做API,能夠經過bound封裝指定的key,而後進行一系列的操做而無須「顯式」的再次指定Key,即BoundKeyOperations:

  • BoundValueOperations
  • BoundSetOperations
  • BoundListOperations
  • BoundSetOperations
  • BoundHashOperations

  

    4. 將事務操做封裝,有容器控制。

    5. 針對數據的「序列化/反序列化」,提供了多種可選擇策略(RedisSerializer)

  • JdkSerializationRedisSerializer:POJO對象的存取場景,使用JDK自己序列化機制,將pojo類經過ObjectInputStream/ObjectOutputStream進行序列化操做,最終redis-server中將存儲字節序列。是目前最經常使用的序列化策略。
  • StringRedisSerializer:Key或者value爲字符串的場景,根據指定的charset對數據的字節序列編碼成string,是「new String(bytes, charset)」和「string.getBytes(charset)」的直接封裝。是最輕量級和高效的策略。
  • JacksonJsonRedisSerializer:jackson-json工具提供了javabean與json之間的轉換能力,能夠將pojo實例序列化成json格式存儲在redis中,也能夠將json格式的數據轉換成pojo實例。由於jackson工具在序列化和反序列化時,須要明確指定Class類型,所以此策略封裝起來稍微複雜。【須要jackson-mapper-asl工具支持】
  • OxmSerializer:提供了將javabean與xml之間的轉換能力,目前可用的三方支持包括jaxb,apache-xmlbeans;redis存儲的數據將是xml工具。不過使用此策略,編程將會有些難度,並且效率最低;不建議使用。【須要spring-oxm模塊的支持】

    針對「序列化和發序列化」中JdkSerializationRedisSerializer和StringRedisSerializer是最基礎的策略,原則上,咱們能夠將數據存儲爲任何格式以便應用程序存取和解析(其中應用包括app,hadoop等其餘工具),不過在設計時仍然不推薦直接使用「JacksonJsonRedisSerializer」和「OxmSerializer」,由於不管是json仍是xml,他們自己仍然是String。

    若是你的數據須要被第三方工具解析,那麼數據應該使用StringRedisSerializer而不是JdkSerializationRedisSerializer。

    若是你的數據格式必須爲json或者xml,那麼在編程級別,在redisTemplate配置中仍然使用StringRedisSerializer,在存儲以前或者讀取以後,使用「SerializationUtils」工具轉換轉換成json或者xml,請參見下文實例。

 

    6. 基於設計模式,和JMS開發思路,將pub/sub的API設計進行了封裝,使開發更加便捷。

    7.spring-data-redis中,並無對sharding提供良好的封裝,若是你的架構是基於sharding,那麼你須要本身去實現,這也是sdr和jedis相比,惟一缺乏的特性。

 

二.簡單實例:

    1) spring配置:

<beans xmlns="http://www.springframework.org/schema/beans" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" default-autowire="byName">
    <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxActive" value="32"></property>
        <property name="maxIdle" value="6"></property>
        <property name="maxWait" value="15000"></property>
        <property name="minEvictableIdleTimeMillis" value="300000"></property>
        <property name="numTestsPerEvictionRun" value="3"></property>
        <property name="timeBetweenEvictionRunsMillis" value="60000"></property>
        <property name="whenExhaustedAction" value="1"></property>
    </bean>
    <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" destroy-method="destroy">
        <property name="poolConfig" ref="jedisPoolConfig"></property>
        <property name="hostName" value="127.0.0.1"></property>
        <property name="port" value="6379"></property>
        <property name="password" value="0123456"></property>
        <property name="timeout" value="15000"></property>
        <property name="usePool" value="true"></property>
    </bean>
    <bean id="jedisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
        <property name="connectionFactory" ref="jedisConnectionFactory"></property>
        <property name="keySerializer">
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
        </property>
        <property name="valueSerializer">
            <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
        </property>
    </bean>
</beans>

 2) 程序實例:

public class SpringDataRedisTestMain {

    /**
     * @param args
     */
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring-redis-beans.xml");
        RedisTemplate redisTemplate = (RedisTemplate)context.getBean("jedisTemplate");
        //其中key採起了StringRedisSerializer
        //其中value採起JdkSerializationRedisSerializer
        ValueOperations<String, User> valueOper = redisTemplate.opsForValue();
        User u1 = new User("zhangsan",12);
        User u2 = new User("lisi",25);
        valueOper.set("u:u1", u1);
        valueOper.set("u:u2", u2);
        System.out.println(valueOper.get("u:u1").getName());
        System.out.println(valueOper.get("u:u2").getName());
    }
    
    /**
     * 若是使用jdk序列化方式,bean必須實現Serializable,且提供getter/setter方法
     * @author qing
     *
     */
    static class User implements Serializable{
        
        /**
         * 
         */
        private static final long serialVersionUID = -3766780183428993793L;
        private String name;
        private Date created;
        private int age;
        public User(){}
        public User(String name,int age){
            this.name = name;
            this.age = age;
            this.created = new Date();
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public Date getCreated() {
            return created;
        }
        public void setCreated(Date created) {
            this.created = created;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        
    }

}

    3) RedisTemplate:

    若是你使用過jedisPool鏈接池,在數據操做以前,你須要pool.getResource()即從鏈接池中獲取「連接資源」(Jedis),在操做以後,你須要(必須)調用pool.returnResource()將資源歸還個鏈接池。可是,spring-data-redis中,咱們彷佛並無直接操做pool,那麼spring是如何作到pool管理的呢??一句話:spring的「看門絕技」--callback。

  •  public <T> T execute(RedisCallback<T> action):這個方法是redisTemplate中執行操做的底層方法,任何基於redisTemplate之上的調用(好比,valueOperations)最終都會被封裝成RedisCallback,redisTemplate在execute方法中將會直接使用jedis客戶端API進行與server通訊,並且在若是使用了鏈接池,則會在操做以後執行returnSource。

其餘實例請參考以下連接:

1) serializer實例

2) operation實例

3) pub/sub實例

相關文章
相關標籤/搜索