电竞比分网-中国电竞赛事及体育赛事平台

分享

Spring-data-redis:特性與實例

 KILLKISS 2014-04-25

Spring-data-redis為spring-data模塊中對redis的支持部分,簡稱為“SDR”,提供了基于jedis客戶端API的高度封裝以及與spring容器的整合,事實上jedis客戶端已經(jīng)足夠簡單和輕量級,而spring-data-redis反而具有“過度設(shè)計”的嫌疑。

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

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

    2) 數(shù)據(jù)操作需要關(guān)注“序列化”/“反序列化”,因為jedis的客戶端API接受的數(shù)據(jù)類型為string和byte,對結(jié)構(gòu)化數(shù)據(jù)(json,xml,pojo等)操作需要額外的支持。

    3) 事務(wù)操作純粹為硬編碼

    4) pub/sub功能,缺乏必要的設(shè)計模式支持,對于開發(fā)者而言需要關(guān)注的太多。

    不過jedis與spring整合,也是非常的簡單,參見“jedis連接池實例”.

 

一.  spring-data-redis針對jedis提供了如下功能

    1. 連接池自動管理,提供了一個高度封裝的“RedisTemplate”類

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

  • ValueOperations:簡單K-V操作
  • SetOperations:set類型數(shù)據(jù)操作
  • ZSetOperations:zset類型數(shù)據(jù)操作
  • HashOperations:針對map類型的數(shù)據(jù)操作
  • ListOperations:針對list類型的數(shù)據(jù)操作

    3. 提供了對key的“bound”(綁定)便捷化操作API,可以通過bound封裝指定的key,然后進行一系列的操作而無須“顯式”的再次指定Key,即BoundKeyOperations:

  • BoundValueOperations
  • BoundSetOperations
  • BoundListOperations
  • BoundSetOperations
  • BoundHashOperations

  

    4. 將事務(wù)操作封裝,有容器控制。

    5. 針對數(shù)據(jù)的“序列化/反序列化”,提供了多種可選擇策略(RedisSerializer)

  • JdkSerializationRedisSerializer:POJO對象的存取場景,使用JDK本身序列化機制,將pojo類通過ObjectInputStream/ObjectOutputStream進行序列化操作,最終redis-server中將存儲字節(jié)序列。是目前最常用的序列化策略。
  • StringRedisSerializer:Key或者value為字符串的場景,根據(jù)指定的charset對數(shù)據(jù)的字節(jié)序列編碼成string,是“new String(bytes, charset)”和“string.getBytes(charset)”的直接封裝。是最輕量級和高效的策略。
  • JacksonJsonRedisSerializer:jackson-json工具提供了javabean與json之間的轉(zhuǎn)換能力,可以將pojo實例序列化成json格式存儲在redis中,也可以將json格式的數(shù)據(jù)轉(zhuǎn)換成pojo實例。因為jackson工具在序列化和反序列化時,需要明確指定Class類型,因此此策略封裝起來稍微復(fù)雜。【需要jackson-mapper-asl工具支持】
  • OxmSerializer:提供了將javabean與xml之間的轉(zhuǎn)換能力,目前可用的三方支持包括jaxb,apache-xmlbeans;redis存儲的數(shù)據(jù)將是xml工具。不過使用此策略,編程將會有些難度,而且效率最低;不建議使用?!拘枰猻pring-oxm模塊的支持】

    針對“序列化和發(fā)序列化”中JdkSerializationRedisSerializer和StringRedisSerializer是最基礎(chǔ)的策略,原則上,我們可以將數(shù)據(jù)存儲為任何格式以便應(yīng)用程序存取和解析(其中應(yīng)用包括app,hadoop等其他工具),不過在設(shè)計時仍然不推薦直接使用“JacksonJsonRedisSerializer”和“OxmSerializer”,因為無論是json還是xml,他們本身仍然是String。

    如果你的數(shù)據(jù)需要被第三方工具解析,那么數(shù)據(jù)應(yīng)該使用StringRedisSerializer而不是JdkSerializationRedisSerializer。

    如果你的數(shù)據(jù)格式必須為json或者xml,那么在編程級別,在redisTemplate配置中仍然使用StringRedisSerializer,在存儲之前或者讀取之后,使用“SerializationUtils”工具轉(zhuǎn)換轉(zhuǎn)換成json或者xml,請參見下文實例。

 

    6. 基于設(shè)計模式,和JMS開發(fā)思路,將pub/sub的API設(shè)計進行了封裝,使開發(fā)更加便捷。

    7.spring-data-redis中,并沒有對sharding提供良好的封裝,如果你的架構(gòu)是基于sharding,那么你需要自己去實現(xiàn),這也是sdr和jedis相比,唯一缺少的特性。

 

二.簡單實例:

    1) spring配置:

Java代碼  收藏代碼
  1. <beans xmlns="http://www./schema/beans"   
  2. xmlns:xsi="http://www./2001/XMLSchema-instance"  
  3. xsi:schemaLocation="http://www./schema/beans http://www./schema/beans/spring-beans.xsd" default-autowire="byName">  
  4.     <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">  
  5.         <property name="maxActive" value="32"></property>  
  6.         <property name="maxIdle" value="6"></property>  
  7.         <property name="maxWait" value="15000"></property>  
  8.         <property name="minEvictableIdleTimeMillis" value="300000"></property>  
  9.         <property name="numTestsPerEvictionRun" value="3"></property>  
  10.         <property name="timeBetweenEvictionRunsMillis" value="60000"></property>  
  11.         <property name="whenExhaustedAction" value="1"></property>  
  12.     </bean>  
  13.     <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" destroy-method="destroy">  
  14.         <property name="poolConfig" ref="jedisPoolConfig"></property>  
  15.         <property name="hostName" value="127.0.0.1"></property>  
  16.         <property name="port" value="6379"></property>  
  17.         <property name="password" value="0123456"></property>  
  18.         <property name="timeout" value="15000"></property>  
  19.         <property name="usePool" value="true"></property>  
  20.     </bean>  
  21.     <bean id="jedisTemplate" class="org.springframework.data.redis.core.RedisTemplate">  
  22.         <property name="connectionFactory" ref="jedisConnectionFactory"></property>  
  23.         <property name="keySerializer">  
  24.             <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>  
  25.         </property>  
  26.         <property name="valueSerializer">  
  27.             <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>  
  28.         </property>  
  29.     </bean>  
  30. </beans>  

    2) 程序?qū)嵗?/p>

Java代碼  收藏代碼
  1. public class SpringDataRedisTestMain {  
  2.   
  3.     /** 
  4.      * @param args 
  5.      */  
  6.     public static void main(String[] args) {  
  7.         ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring-redis-beans.xml");  
  8.         RedisTemplate redisTemplate = (RedisTemplate)context.getBean("jedisTemplate");  
  9.         //其中key采取了StringRedisSerializer  
  10.         //其中value采取JdkSerializationRedisSerializer  
  11.         ValueOperations<String, User> valueOper = redisTemplate.opsForValue();  
  12.         User u1 = new User("zhangsan",12);  
  13.         User u2 = new User("lisi",25);  
  14.         valueOper.set("u:u1", u1);  
  15.         valueOper.set("u:u2", u2);  
  16.         System.out.println(valueOper.get("u:u1").getName());  
  17.         System.out.println(valueOper.get("u:u2").getName());  
  18.     }  
  19.       
  20.     /** 
  21.      * 如果使用jdk序列化方式,bean必須實現(xiàn)Serializable,且提供getter/setter方法 
  22.      * @author qing 
  23.      * 
  24.      */  
  25.     static class User implements Serializable{  
  26.           
  27.         /** 
  28.          *  
  29.          */  
  30.         private static final long serialVersionUID = -3766780183428993793L;  
  31.         private String name;  
  32.         private Date created;  
  33.         private int age;  
  34.         public User(){}  
  35.         public User(String name,int age){  
  36.             this.name = name;  
  37.             this.age = age;  
  38.             this.created = new Date();  
  39.         }  
  40.         public String getName() {  
  41.             return name;  
  42.         }  
  43.         public void setName(String name) {  
  44.             this.name = name;  
  45.         }  
  46.         public Date getCreated() {  
  47.             return created;  
  48.         }  
  49.         public void setCreated(Date created) {  
  50.             this.created = created;  
  51.         }  
  52.         public int getAge() {  
  53.             return age;  
  54.         }  
  55.         public void setAge(int age) {  
  56.             this.age = age;  
  57.         }  
  58.           
  59.     }  
  60.   
  61. }  

    3) RedisTemplate:

    如果你使用過jedisPool連接池,在數(shù)據(jù)操作之前,你需要pool.getResource()即從連接池中獲取“鏈接資源”(Jedis),在操作之后,你需要(必須)調(diào)用pool.returnResource()將資源歸還個連接池。但是,spring-data-redis中,我們似乎并沒有直接操作pool,那么spring是如何做到pool管理的呢??一句話:spring的“看門絕技”--callback。

  •  public <T> T execute(RedisCallback<T> action):這個方法是redisTemplate中執(zhí)行操作的底層方法,任何基于redisTemplate之上的調(diào)用(比如,valueOperations)最終都會被封裝成RedisCallback,redisTemplate在execute方法中將會直接使用jedis客戶端API進行與server通信,而且在如果使用了連接池,則會在操作之后執(zhí)行returnSource。

其他實例請參考如下鏈接:

1) serializer實例

2) operation實例

3) pub/sub實例

 

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多