Spring-data-redis 第一天(操作list和hash)

来源:互联网 发布:2017年php好找工作吗 编辑:程序博客网 时间:2024/06/15 07:08

1.Redis

   这就不必哆嗦了,Redis 支持丰富的数据类型,String ,List,Sets ,Sorted Sets,Hashes,这就可以看出Java 操作Redis就要针对各种类型都有自己的操作。这里自己学习的是Spring-data-redis 中基于Jedis connection的不过在RedisTemplate 中 可不管这些,全部都是 connect 的操作,所以 我想说,记得引Jedis的Jar包,而且还要是2.0以上的哦

 

2.安装Redis

   这也不罗嗦了,这里简单说下Redis cli 中的简单操作

   (1) String

         SET NAME ZHANG

         GET NAME

          INCR ,APPEND GETRANGE,MSET,STRLENGTH.

    (2) LIST

         LPUSH name zhang

         LPUSH name hao ni zhen shi yi ge SB

         LLEN name

         LREM name xx

     (3)SETS

         SADD name zhang

         SADD name zhang

         SADD name hao

         SMEMBERS name

     (4) Sorted Sets

       ZADD name 1 zhang

       ZADD name 2 hao

       ZRANGE

      (5)HASHes

          HSET name:1 name zhang

          HSET name:1 last     hao

          HGET name:1 name

          HGETALL name:1

3.简单的用Spring-data-redis

   当然 关联的Jar 包用Maven 来搞,(前段时间Maven不好使,生不如死呀,各种看错误来加Jar包),然后就是在Spring  applicationContext,xml中配置了

      首先:Jedis 的连接池:redis.clients.jedis.JedisPoolConfig 见仁见智

 

Java代码  收藏代码
  1. <!-- 配置Jedis的 缓冲池 -->  
  2. <bean id="JedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"  
  3.     p:maxActive="32"  
  4.     p:maxIdle="6"  
  5.     p:maxWait="15000"  
  6.     p:minEvictableIdleTimeMillis="300000"  
  7.     p:numTestsPerEvictionRun="3"  
  8.     p:timeBetweenEvictionRunsMillis="60000"  
  9.     p:whenExhaustedAction="1">  
  10. </bean>  

     第二,创建ConnectionFactory

 

 

Java代码  收藏代码
  1. <!-- 配置Jedis connection -->     
  2.     <bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"  
  3.     p:poolConfig-ref="JedisPoolConfig"  
  4.     p:hostName="192.168.137.100"  
  5.     p:port="6379"  
  6.     p:usePool="true"  
  7.     >  
  8.     </bean>  

     第三:创建RedisTemplate

 

 

Java代码  收藏代码
  1. <!-- 配置 redisTemplate 利用Stringserializer -->  
  2.     <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"  
  3.     p:connectionFactory-ref="connectionFactory"   
  4.     >  
  5.     <property name="defaultSerializer">    
  6.             <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>    
  7.         </property>    
  8.     </bean>  

    由于redis中存储的数据必须是经过序列化的,所以Spring-data-redis中采取了几种序列化模式,有自带的JDKblablabla,还有StringRedisSerializer,

但是Json 和XML也都是基于String类型的所以就在默认文件中使用String类型的序列化,而默认是JdkSerializationRedisSerializer.

Java代码  收藏代码
  1. public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperations<K, V> {  
  2.   
  3.     private boolean exposeConnection = false;  
  4.     private boolean initialized = false;  
  5.     private boolean enableDefaultSerializer = true;  
  6.     private RedisSerializer<?> defaultSerializer = new JdkSerializationRedisSerializer();  

 

 

 先不管那么多了,来做点简单的实验。

1.String

 

Java代码  收藏代码
  1. RedisTemplate rt = (RedisTemplate) context.getBean("redisTemplate");  
  2.           
  3. rt.opsForValue().set("zhang""hao");  
  4.           
  5. System.out.println(rt.opsForValue().get("zhang"));  
  6.           

 

2.List

  说到List  Redis 提供了类似于消息队列的操作,先看下接口,从名字上就可以看到这些操作的意义,我就简单实例一下。

Java代码  收藏代码
  1. public interface ListOperations<K, V> {  
  2.   
  3.     List<V> range(K key, long start, long end);  
  4.   
  5.     void trim(K key, long start, long end);  
  6.   
  7.     Long size(K key);  
  8.   
  9.     Long leftPush(K key, V value);  
  10.   
  11.     Long leftPushAll(K key, V... values);  
  12.   
  13.     Long leftPushIfPresent(K key, V value);  
  14.   
  15.     Long leftPush(K key, V pivot, V value);  
  16.   
  17.     Long rightPush(K key, V value);  
  18.   
  19.     Long rightPushAll(K key, V... values);  
  20.   
  21.     Long rightPushIfPresent(K key, V value);  
  22.   
  23.     Long rightPush(K key, V pivot, V value);  
  24.   
  25.     void set(K key, long index, V value);  
  26.   
  27.     Long remove(K key, long i, Object value);  
  28.   
  29.     V index(K key, long index);  
  30.   
  31.     V leftPop(K key);  
  32.   
  33.     V leftPop(K key, long timeout, TimeUnit unit);  
  34.   
  35.     V rightPop(K key);  
  36.   
  37.     V rightPop(K key, long timeout, TimeUnit unit);  
  38.   
  39.     V rightPopAndLeftPush(K sourceKey, K destinationKey);  
  40.   
  41.     V rightPopAndLeftPush(K sourceKey, K destinationKey, long timeout, TimeUnit unit);  
  42.   
  43.     RedisOperations<K, V> getOperations();  

 PS.我上面贴的源码是 github上面的最新源码。我自己用的还是1.01  泪千行,我说找了半天rightpushAll 竟然找不到。所以 记得用最新的版本。

Java代码  收藏代码
  1. String KEYS="LIST:";  
  2. rt.opsForList().rightPush(KEYS, "zhang");  
  3. rt.opsForList().leftPush(KEYS, "HAO");  
  4.          // sort : HAO zhang  
  5. for(int i=0;i<=rt.opsForList().size(KEYS);i++){  
  6.               
  7. System.out.println(rt.opsForList().rightPop(KEYS));  
  8. }  

 

3 Hashes (SETS 自己看看吧。。)

Java代码  收藏代码
  1. String KEYS="HASH:";  
  2.         rt.opsForHash().put(KEYS, "name""zhang");  
  3.         rt.opsForHash().put(KEYS, "last""hao");  
  4.         rt.opsForHash().put(KEYS, "wo""ni");  
  5.         rt.opsForHash().put(KEYS, "name""sb");  
  6.           
  7.         System.out.println(rt.opsForHash().get(KEYS, "name"));  

 

可以看到key name 被覆盖了,其中有个BooleanputIfAbsent(Hkey,HKhashKey,HVvalue) 方法,这个具体细节就自己看看吧。下面把Hashoperations 里面的方法贴下:

Java代码  收藏代码
  1. public interface HashOperations<H, HK, HV> {  
  2.   
  3.     void delete(H key, Object... hashKeys);  
  4.   
  5.     Boolean hasKey(H key, Object hashKey);  
  6.   
  7.     HV get(H key, Object hashKey);  
  8.   
  9.     List<HV> multiGet(H key, Collection<HK> hashKeys);  
  10.   
  11.     Long increment(H key, HK hashKey, long delta);  
  12.   
  13.     Double increment(H key, HK hashKey, double delta);  
  14.   
  15.     Set<HK> keys(H key);  
  16.   
  17.     Long size(H key);  
  18.   
  19.     void putAll(H key, Map<? extends HK, ? extends HV> m);  
  20.   
  21.     void put(H key, HK hashKey, HV value);  
  22.   
  23.     Boolean putIfAbsent(H key, HK hashKey, HV value);  
  24.   
  25.     List<HV> values(H key);  
  26.   
  27.     Map<HK, HV> entries(H key);  
  28.   
  29.     RedisOperations<H, ?> getOperations();  
  30. }  

 今天就先到这里,Redis 还有很多东西,比如cache transcation 等等 看下目录结构

还有比较多东西,明天继续 再接再厉!


{事务}

从今天开始,开始慢慢学习Spring 对 redis 中各种特性的支持,事务啦,pipeline啦,sharding啦,cache啦,还有就是分布式中和用jedispool 等等之中的东西,东西好多呀。头大了。。

 

1.首先看Jedis 原生态的对事务的处理

 

Java代码  收藏代码
  1. Jedis jedis = new Jedis("192.168.137.100",6379);  
  2. Transaction tx = jedis.multi();  
  3.           
  4. for(int i=0;i<1000; i++){  
  5.     tx.set("zhang"+i, "hao"+i);  
  6. }  
  7. List<Object> result = tx.exec();  
  8.           
  9. jedis.disconnect();  

 其中可以用Jedis 的 watch(key) 来实现乐观锁,有一点,如果事务处理器中出现错误,不会回滚,出错那条不会处理,还有Jedis的 discard 方法来取消事务,可以自己模拟多线程来看看这两个方法的使用,还有一点,事务是异步执行,所以不能再事务中调用get 同步查询结果,都是坑呀。。。。

 

2.Spring中对Redis 事务的支持

 (1)

Java代码  收藏代码
  1.               rt.watch("zhang");  
  2. rt.multi();  
  3. for(int i=0;i<10;i++){  
  4.     BoundHashOperations<String, String, String> hs = rt.boundHashOps("zhang");  
  5.     hs.put("zhang"+i, "hao"+i);  
  6. }  
  7. rt.exec();  

   我们按照上面的思路,然后写下了上面这段代码。然后就报错了: java.lang.NullPointerException,

好吧 看下面一段代码:

Java代码  收藏代码
  1. SessionCallback<String> sessionCallback = new SessionCallback<String>() {  
  2.               
  3.             @Override  
  4.             public <K, V> String execute(RedisOperations<K, V> operation)  
  5.                     throws DataAccessException {  
  6.                   
  7.                 operation.multi();  
  8.                 for(int i=0;i<10;i++){  
  9.                     BoundHashOperations<String, String, String> hs = ((RedisTemplate)operation).boundHashOps("zhang");  
  10.                     hs.put("zhang"+i, "hao"+i);  
  11.                 }  
  12.                 operation.exec();  
  13.                 return null;  
  14.             }  
  15.         };  
  16.         rt.execute(sessionCallback);  

 这段代码就执行成功了,为什么呢。只有Google 大神们是怎么解释了:

首先还是看源码:

Java代码  收藏代码
  1. public void multi() {  
  2.         execute(new RedisCallback<Object>() {  
  3.   
  4.             public Object doInRedis(RedisConnection connection) throws DataAccessException {  
  5.                 connection.multi();  
  6.                 return null;  
  7.             }  
  8.         }, true);  
  9.     }  

 这里要实现一个指定返回类型的RedisCallback接口,这个接口只有一个函数doInRedis

doInRedis的参数是RedisConnection接口,spring-data-redis针对不的Redis Java Client都有对应的 RedisConnection实现:

JedisConnection

JredisConnection

RjcConnection

SrpConnection

目的就是将不同Client的API统一了一下,可以看成是Adapter吧 。

 

execute这个是模板函数,主是处理连接的问题。

spring-data-redis 针对不的 Redis Java Client 也都实现了相应的 RedisConnectionFactory,来获取连接。  

 

比如 JedisConnectionFactory 内部是通过 JedisPool 来实现连接工厂。

Java代码  收藏代码
  1. public <T> T execute(RedisCallback<T> action, boolean exposeConnection, boolean pipeline) {    
  2.     Assert.notNull(action, "Callback object must not be null");    
  3.     
  4.     RedisConnectionFactory factory = getConnectionFactory();    
  5.     RedisConnection conn = RedisConnectionUtils.getConnection(factory);    
  6.     
  7.     boolean existingConnection = TransactionSynchronizationManager.hasResource(factory);    
  8.     preProcessConnection(conn, existingConnection);    
  9.     
  10.     boolean pipelineStatus = conn.isPipelined();    
  11.     if (pipeline && !pipelineStatus) {    
  12.         conn.openPipeline();    
  13.     }    
  14.     
  15.     try {    
  16.         RedisConnection connToExpose = (exposeConnection ? conn : createRedisConnectionProxy(conn));    
  17.         T result = action.doInRedis(connToExpose);    
  18.     
  19.         // close pipeline    
  20.         if (pipeline && !pipelineStatus) {    
  21.             conn.closePipeline();    
  22.         }    
  23.     
  24.         // TODO: any other connection processing?    
  25.         return postProcessResult(result, conn, existingConnection);    
  26.     } finally {    
  27.         RedisConnectionUtils.releaseConnection(conn, factory);    
  28.     }    
  29. }    

 可以看到,正常情况下每次connection都是新的,那上上一段代码中得multi 就没用了。

这样。好吧 我懒得复制了,可以看下这个大神的博客:http://jimgreat.iteye.com/blog/1596058 讲的很清楚sessioncallback如何捆绑session。

 

 

http://stackoverflow.com/questions/10750626/transactions-and-watch-statement-in-redis  这段解释了watch的操作,非常明白 一看就懂,


原创粉丝点击