Redis項目實戰---應用及理論(三)---Jedis使用

Jedis即redis java客戶端,源碼地址:https://github.com/xetorthio/jedis

pom配置:

<dependency>
   <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.0.1</version>
    <type>jar</type>
    <scope>compile</scope>
</dependency>
 
 
1)連接單機版
     public void testJedis() throws Exception {
          // 第一步:創建一個Jedis對象。需要指定服務端的ip及端口。
          Jedis jedis = new Jedis("192.168.**.**", 6379);
          // 第二步:使用Jedis對象操作數據庫,每個redis命令對應一個方法。
          String result = jedis.get("hello");
          // 第三步:打印結果。
          System.out.println(result);
          // 第四步:關閉Jedis
          jedis.close();
     }

2) 連接單機版使用連接池

     public void testJedisPool() throws Exception {
          // 第一步:創建一個JedisPool對象。需要指定服務端的ip及端口。
          JedisPool jedisPool = new JedisPool("192.168.**.**", 6379);
          // 第二步:從JedisPool中獲得Jedis對象。
          Jedis jedis = jedisPool.getResource();
          // 第三步:使用Jedis操作redis服務器。
          jedis.set("jedis", "test");
          String result = jedis.get("jedis");
          System.out.println(result);
          // 第四步:操作完畢後關閉jedis對象,連接池回收資源。
          jedis.close();
          // 第五步:關閉JedisPool對象。
          jedisPool.close();
     }
3) 連接集羣版
     public void testJedisCluster() throws Exception {
          // 第一步:使用JedisCluster對象。需要一個Set<HostAndPort>參數。Redis節點的列表。
          Set<HostAndPort> nodes = new HashSet<>();
          nodes.add(new HostAndPort("192.168.**.**", 7001));
          nodes.add(new HostAndPort("192.168.**.**", 7002));
          nodes.add(new HostAndPort("192.168.**.**", 7003));
          nodes.add(new HostAndPort("192.168.**.**", 7004));
          nodes.add(new HostAndPort("192.168.**.**", 7005));
          nodes.add(new HostAndPort("192.168.**.**", 7006));
          JedisCluster jedisCluster = new JedisCluster(nodes);
          // 第二步:直接使用JedisCluster對象操作redis。在系統中單例存在。
          jedisCluster.set("hello", "100");
          String result = jedisCluster.get("hello");
          // 第三步:打印結果
          System.out.println(result);
          // 第四步:系統關閉前,關閉JedisCluster對象。
          jedisCluster.close();
     }
 
4)JedisPool初始化配置:
private static final int taskCount = 50; // 併發任務 
private static final int batchSize = 10; // pipeline大小 
private static final int cmdCount = 1000;// 每個任務處理命令數 
private static final boolean usePipeline = true;
 
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxActive(200);
poolConfig.setMaxIdle(100);
poolConfig.setMaxWait(2000);
poolConfig.setTestOnBorrow(false);
poolConfig.setTestOnReturn(false);
jedisPool = new JedisPool(poolConfig, host, port);

5)Jedis 消息發佈與訂閱API

   5.1)消息訂閱

   

   public void subscribeChannal(){
//從jedisPool中獲取一個jedis對象 Jedis jds
= RedisInsUtil.getJedis(); // 方式1 訂閱得到信息在lister的onPMessage(...)方法中進行處理 jds.psubscribe(this, new String[]{"channal01","channal02"});
   // 方式2 訂閱得到信息在lister的onMessage(...)方法中進行處理 (普通訂閱方式)    //jedis.subscribe(listener, "foo", "watson");
} // 初始化訂閱時候的處理 @Override public void onSubscribe(String channel, int subscribedChannels) { } // 初始化按表達式的方式訂閱時候的處理 @Override public void onPSubscribe(String pattern, int subscribedChannels) { } @Override // 取得按表達式的方式訂閱的消息後的處理 public void onPMessage(String pattern, String channel, String message) { LOG.info("onPMessage()," + pattern + "=" + channel + ",msg="+ message); } // 取得訂閱的消息後的處理 public void onMessage(String channel, String message) { }

     5.2)消息發佈

             發佈消息只用調用Jedis的publish(...)方法即可。

    Jedis jedis = ru.getConnection(); //獲取一個jedis對象,自行封裝工具類 
    jedis.publish("hello_foo", "bar123");  

 

6) 管道

原理:
    Redis客戶端與Redis服務器之間使用TCP協議進行連接,管道(pipeline)可以一次性發送多條命令並在執行完後一次性將結果返回,pipeline通過減少客戶端與redis的通信次數來實現降低往返延時時間,而且Pipeline 實現的原理是隊列,而隊列的原理是時先進先出,這樣就保證數據的順序性。 
    缺陷:需要注意到是用 pipeline方式打包命令發送,redis必須在處理完所有命令前先緩存起所有命令的處理結果。打包的命令越多,緩存消耗內存也越多。所以並不是打包的命令越多越好。具體多少合適需要根據具體情況測試。
   備註:Pipeline 的默認的同步的個數爲53個,也就是說arges中累加到53條數據時會把數據提交;
  
7)擴展:
    由於redis-cluster的hash分片,JedisCluster對象原生並不支持Pipline管道和keys方法。然而,實際項目中在追求性能以及考慮到Redis集羣版和單機版兼容或切換問題,往往需要支持這些方法,通過整理網上的部分資料,現給出以下思路,具體方法可參考gitHub示例
   
  管道Pipline實現思路:
 
  Redis集羣規範: Redis 集羣的鍵空間被分割爲 16384 個槽(slot), 集羣的最大節點數量也是 16384 個。每個主節點都負責處理 16384 個哈希槽的其中一部分。當一個集羣處於“穩定”(stable)狀態時(羣沒有在執行重配置(reconfiguration)操作), 每個哈希槽都只由一個節點進行處理(hash Slot的分配是由CRC16算法計算)。
 故, 

  1.根據要插入的key知道這個key所對應的槽的號碼(JedisClusterCRC16.getSlot(key)), 再通過這個槽的號碼從集羣中找到對應Jedis(通過每個節點的slot分佈,就知道了哪些key應該在哪些節點上)。

  2.相同槽位的key,使用同一個jedis.pipeline去執行命令。

  3.合併此次pipeline所有的response返回。

 

  keys實現思路:

     循環集羣中所有的節點(分別獲取j對應的client對象),然後每個節點做keys,最後再加到一塊返回。

   

  備註:每次執行前需要刷新以獲取最新的slot分佈。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章