不做浮躁的人
正在行走的人...
posts - 77,  comments - 51,  trackbacks - 0
因为一直用spring,所以上redis,决定用spring-data-redis,该项目希望用maven或者gradle,暂时不打算学习gradle,于是把maven学习了下,并留下学习备忘。

spring data redis推荐jedis,因此稍微把jedis稍微看了下,jedis是redis的java客户端。

sdr支持低层次的通过连接器connector连接到Redis,支持高层次的友好的模板类RedisTemplate,RedisTemplate是建立在低级别的connection基础之上。RedisConnection接收或返回字节数组需要自身处理连接,比如关闭连接,而RedisTemplate负责处理串行化和反串行化,并且管理对连接进行管理。RedisTemplate提供操作视图,比如(Bound)ValueOperations,
(Bound)ListOperations,(Bound)SetOperations,(Bound)ZSetOperations,(Bound)HashOperations。RedisTemplate是线程安全的,能够用于多个实例中。

RedisTemplate默认选择java-based串行化,也可以切换为其它的串行化方式,或者设置enabledDefaultSerializer为false或者设置串行化器为null,则RedisTemplate用raw byte arrays表示数据。

sdr连接到redis通过RedisConnectionFactory来获得有效的RedisConnection。RedisConnection负责建立和处理和redis后端通信。RedisConnection提供getNativeconnection返回用来通信的底层connection。

spring配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:p="http://www.springframework.org/schema/p"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
  <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
        p:host-name="server" p:port="6379" p:use-pool="true"/>
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"
    p:connection-factory-ref="jedisConnectionFactory"/>
</beans>

使用样例:
public class Example {

  // 注入实际的模板
  @Autowired
  private RedisTemplate<String, String> template;//表示键值都是字符串类型。

  // 注入模板为ListOperations.
  @Resource(name="redisTemplate")
  private ListOperations<String, String> listOps;

  public void addLink(String userId, URL url) {
    listOps.leftPush(userId, url.toExternalForm());
  }
}

由于大部分Redis键值对存储都是键值均为字符串,因此sdr做了两个扩展,即StringRedisConnection以及StringRedisTemplate,两个扩展均采用StringRedisSerializer。

<bean id="stringRedisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate"
    p:connection-factory-ref="jedisConnectionFactory"/>

代码示例:
@Autowired
  private StringRedisTemplate redisTemplate;

  public void addLink(String userId, URL url) {
    redisTemplate.opsForList().leftPush(userId, url.toExternalForm());
  }

RedisTemplate以及其子类都允许开发者通过RedisCallback直接跟Redis通信,在callback中,开发者获得RedisConnection。StringRedisTemplate在callback中可以获得StringRedisConnection,需要强制转换。

利用Redis实现Jms的发布和订阅的功能:
发布信息:可以通过RedisConnection或者RedisTemplate来实现。
redisConnection.publish(byte[] msg,byte[] channel);
template.convertAndSend("hello!","world");
接收消息:在接受放,可以订阅根据频道名来订阅一个或多个频道或者通过模式匹配。模式匹配非常有用,因为它不仅允许一个命令创建多个订阅,也能监听在订阅创建之后产生的新的频道(只要匹配指定的模式)。
在低层面上,RedisConnection提供subscribe和pSubscribe(根据模式匹配)方法,多个频道和模式可以一起作为参数,RedisConnection也提供了getSubscription和isSubscribed方法。当用jedis连接器时,订阅命令是同步的,因此会产生堵塞,会导致该线程一直等待消息,只有当订阅取消的时候,才释放线程,采用unsubcribe或pUnsubscribe来取消同线程的订阅。为了处理订阅消息,需要实现MessageListener callback,每次当新的消息达到时,会调用callback执行onMessage方法,该方法能够获得消息,频道,以及匹配的模式。

由于MessageListener的天然堵塞,底层面的消息接收不太被人接受,而且它要求处理连接和线程的管理,为了规避这个问题,sdr提供RedisMessageListenerContainer,它被用来接受从Redis频道传来的消息并注入MessageListener,RedisMessageListenerContainer负责相应接受消息的线程并派发到处理的监听器中。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:redis="http://www.springframework.org/schema/redis"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/redis http://www.springframework.org/schema/redis/spring-redis.xsd">

  <!-- the default ConnectionFactory -->
  <redis:listener-container>
    <!-- the method attribute can be skipped as the default method name is "handleMessage" -->
    <redis:listener ref="listener" method="handleMessage" topic="chatroom" />
  </redis:listener-container>
 
  <bean id="listener" class="redisexample.DefaultMessageDelegate"/>
  ...
<beans>

redis对事务提供支持,包括multi,exec,discard命令,这些命令也能用于RedisTemplate,然后redisTemplate不保证用相同的连接在同一个事务执行所有操作。sdr提供SessionCallback接口用于同线程的多操作执行。

Redis支持管道(pipelining),管道可以发送多个命令到服务端无需等待反馈然后读取单一步的反馈。管道在你需要一行发送多个命令是提升性能,比如对相同的列表增加多个元素。如果不关注管道操作的结果,则可以调用RedisTemplate标准的excute方法,传递true作为pipeline参数。excutePipelined方法执行RedisCallback或者sessionCallback,然后返回结果。

List<Object> results = stringRedisTemplate.executePipelined(new RedisCallback<Object>() {
    public Object doInRedis(RedisConnection connection) throws DataAccessException {
        StringRedisConnection stringRedisConn = (StringRedisConnection)connection;
        for(int i=0; i< batchSize; i++) {
            stringRedisConn.rPop("myqueue");
        }
        return null;//必须返回null
    }
});//results为myqueue的value。

Redis2.6以及更高的版本支持通过eval和evalsha命令执行lua script。sdr封装代码执行,串行化以及利用代码缓存。scripts能够通过RedisTemplate的execute方法来运行,RedisTemplate用一个可配置的ScriptExecutor来执行提供的代码。缺省的ScriptExecutor通过获取代码的sha1,尝试运行evalsha,失败后执行eval。

lua script一般用于原子操作且命令的行为被另外的命令结果所影响。

配置:
<bean id="script" class="org.springframework.data.redis.core.script.DefaultRedisScript">
        <property name="location" value="classpath:META-INF/scripts/checkandset.lua"/>
        <property name="resultType" value="java.lang.Boolean"/>
    </bean>

java代码:
@Autowired
    RedisScript<Boolean> script;

    public boolean checkAndSet(String expectedValue, String newValue) {
        return redisTemplate.execute(script, Collections.singletonList("key"),
            expectedValue, newValue);
    }

lua script:
-- checkandset.lua
local current = redis.call('GET', KEYS[1])
if current == ARGV[1]
then
    redis.call('SET', KEYS[1], ARGV[2])
    return true
end
return false
redis支持类存放在org.springframework.data.redis.support,RedisSet和RedisZSet提供Redis支持的intersection以及union等方法。RedisList可以实现Queue以及Deque来实现FIFO和LiFO。
配置:
<bean id="queue" class="org.springframework.data.redis.support.collections.DefaultRedisList">
    <constructor-arg ref="redisTemplate"/>
    <constructor-arg value="queue-key"/>
  </bean>
代码:
// injected
  private Deque<String> queue;

  public void addTag(String tag) {
    queue.push(tag);
  }

Sdr提供了一个spring3.1 cache abstraction的实现。配置:
<bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager" c:template-ref="redisTemplate"/>





posted on 2014-02-08 18:51 不做浮躁的人 阅读(26151) 评论(0)  编辑  收藏

只有注册用户登录后才能发表评论。


网站导航:
 

<2014年2月>
2627282930311
2345678
9101112131415
16171819202122
2324252627281
2345678

常用链接

留言簿(8)

随笔分类(31)

随笔档案(75)

文章分类(1)

文章档案(3)

搜索

  •  

最新评论

阅读排行榜

评论排行榜