不做浮躁的人
          正在行走的人...
          posts - 171,  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 不做浮躁的人 閱讀(26887) 評論(0)  編輯  收藏

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           

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

          常用鏈接

          留言簿(9)

          隨筆分類(31)

          隨筆檔案(75)

          文章分類(1)

          文章檔案(3)

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 专栏| 定兴县| 乐至县| 泰安市| 南通市| 昭平县| 大余县| 玉山县| 霍城县| 五寨县| 松溪县| 乡宁县| 西安市| 东乡族自治县| 启东市| 贵溪市| 铁岭县| 巢湖市| 朔州市| 屏东县| 华宁县| 栖霞市| 镇宁| 蒲江县| 英德市| 东港市| 义乌市| 青铜峡市| 黔江区| 静安区| 双鸭山市| 伊吾县| 鄂托克旗| 潞西市| 延庆县| 鞍山市| 奉化市| 利津县| 玉山县| 休宁县| 瓦房店市|