1. 程式人生 > >jedis操作redis的幾種方式

jedis操作redis的幾種方式

redis是一個著名的key-value儲存系統,也是nosql中的最常見的一種。其實,個人認為,redis最強大的地方不在於其儲存,而在於其強大的快取作用。

我們可以把它想象成一個巨大的(多借點叢集,聚合多借點的記憶體)的Map,也就是Key-Value。

所以,我們可以把它做成快取元件。

官方推薦的java版客戶端是jedis,非常強大和穩定,支援事務、管道及有jedis自身實現。我們對redis資料的操作,都可以通過jedis來完成。

那我們就來看一看,jedis不同的呼叫方式:

(1)普通同步方式

這是一種最簡單和最基礎的呼叫方式,對於簡單的資料存取需求,我們可以通過這種方式呼叫。

public void jedisNormal() {
    Jedis jedis = new Jedis("localhost");
    long start = System.currentTimeMillis();
    for (int i = 0; i < 100000; i++) {
        String result = jedis.set("n" + i, "n" + i);
    }
    long end = System.currentTimeMillis();
    System.out.println("Simple SET: " + ((end - start)/1000.0) + " seconds");
    jedis.disconnect();
}
//每次set之後都可以返回結果,標記是否成功。


(2)事務方式(Transactions)

所謂事務,即一個連續操作,是否執行是一個事務,要麼完成,要麼失敗,沒有中間狀態。

而redis的事務很簡單,他主要目的是保障,一個client發起的事務中的命令可以連續的執行,而中間不會插入其他client的命令,也就是事務的連貫性。

public void jedisTrans() {
    Jedis jedis = new Jedis("localhost");
    long start = System.currentTimeMillis();
    Transaction tx = jedis.multi();
    for (int i = 0; i < 100000; i++) {
        tx.set("t" + i, "t" + i);
    }
    List<Object> results = tx.exec();
    long end = System.currentTimeMillis();
    System.out.println("Transaction SET: " + ((end - start)/1000.0) + " seconds");
    jedis.disconnect();
}
//我們呼叫jedis.watch(…)方法來監控key,如果呼叫後key值發生變化,則整個事務會執行失敗。另外,事務中某個操作失敗,並不會回滾其他操作。這一點需要注意。還有,我們可以使用discard()方法來取消事務。


(3)管道(Pipelining)

管道是一種兩個程序之間單向通訊的機制。

那再redis中,為何要使用管道呢?有時候,我們需要採用非同步的方式,一次傳送多個指令,並且,不同步等待其返回結果。這樣可以取得非常好的執行效率。

public void jedisPipelined() {
    Jedis jedis = new Jedis("localhost");
    Pipeline pipeline = jedis.pipelined();
    long start = System.currentTimeMillis();
    for (int i = 0; i < 100000; i++) {
        pipeline.set("p" + i, "p" + i);
    }
    List<Object> results = pipeline.syncAndReturnAll();
    long end = System.currentTimeMillis();
    System.out.println("Pipelined SET: " + ((end - start)/1000.0) + " seconds");
    jedis.disconnect();
}


(4)管道中呼叫事務

對於,事務以及管道,這兩個概念我們都清楚了。

在某種需求下,我們需要非同步執行命令,但是,又希望多個命令是有連續的,所以,我們就採用管道加事務的呼叫方式。jedis是支援在管道中呼叫事務的。

public void jedisCombPipelineTrans() {
    jedis = new Jedis("localhost"); 
    long start = System.currentTimeMillis();
    Pipeline pipeline = jedis.pipelined();
    pipeline.multi();
    for (int i = 0; i < 100000; i++) {
        pipeline.set("" + i, "" + i);
    }
    pipeline.exec();
    List<Object> results = pipeline.syncAndReturnAll();
    long end = System.currentTimeMillis();
    System.out.println("Pipelined transaction: " + ((end - start)/1000.0) + " seconds");
    jedis.disconnect();
}
//效率上可能會有所欠缺


(5)分散式直連同步呼叫

這個是分散式直接連線,並且是同步呼叫,每步執行都返回執行結果。類似地,還有非同步管道呼叫。

其實就是分片。

public void jedisShardNormal() {
    List<JedisShardInfo> shards = Arrays.asList(
            new JedisShardInfo("localhost",6379),
            new JedisShardInfo("localhost",6380));
 
    ShardedJedis sharding = new ShardedJedis(shards);
 
    long start = System.currentTimeMillis();
    for (int i = 0; i < 100000; i++) {
        String result = sharding.set("sn" + i, "n" + i);
    }
    long end = System.currentTimeMillis();
    System.out.println("[email protected] SET: " + ((end - start)/1000.0) + " seconds");
 
    sharding.disconnect();
}


(6)分散式直連非同步呼叫

public void jedisShardpipelined() {
    List<JedisShardInfo> shards = Arrays.asList(
            new JedisShardInfo("localhost",6379),
            new JedisShardInfo("localhost",6380));
 
    ShardedJedis sharding = new ShardedJedis(shards);
 
    ShardedJedisPipeline pipeline = sharding.pipelined();
    long start = System.currentTimeMillis();
    for (int i = 0; i < 100000; i++) {
        pipeline.set("sp" + i, "p" + i);
    }
    List<Object> results = pipeline.syncAndReturnAll();
    long end = System.currentTimeMillis();
    System.out.println("[email protected] SET: " + ((end - start)/1000.0) + " seconds");
 
    sharding.disconnect();
}


(7)分散式連線池同步呼叫

如果,你的分散式呼叫程式碼是執行線上程中,那麼上面兩個直連呼叫方式就不合適了,因為直連方式是非執行緒安全的,這個時候,你就必須選擇連線池呼叫。

連線池的呼叫方式,適合大規模的redis叢集,並且多客戶端的操作。

public void jedisShardSimplePool() {
    List<JedisShardInfo> shards = Arrays.asList(
            new JedisShardInfo("localhost",6379),
            new JedisShardInfo("localhost",6380));
 
    ShardedJedisPool pool = new ShardedJedisPool(new JedisPoolConfig(), shards);
 
    ShardedJedis one = pool.getResource();
 
    long start = System.currentTimeMillis();
    for (int i = 0; i < 100000; i++) {
        String result = one.set("spn" + i, "n" + i);
    }
    long end = System.currentTimeMillis();
    pool.returnResource(one);
    System.out.println("[email protected] SET: " + ((end - start)/1000.0) + " seconds");
 
    pool.destroy();
}


(8)分散式連線池非同步呼叫

public void jedisShardPipelinedPool() {
    List<JedisShardInfo> shards = Arrays.asList(
            new JedisShardInfo("localhost",6379),
            new JedisShardInfo("localhost",6380));
 
    ShardedJedisPool pool = new ShardedJedisPool(new JedisPoolConfig(), shards);
 
    ShardedJedis one = pool.getResource();
 
    ShardedJedisPipeline pipeline = one.pipelined();
 
    long start = System.currentTimeMillis();
    for (int i = 0; i < 100000; i++) {
        pipeline.set("sppn" + i, "n" + i);
    }
    List<Object> results = pipeline.syncAndReturnAll();
    long end = System.currentTimeMillis();
    pool.returnResource(one);
    System.out.println("[email protected] SET: " + ((end - start)/1000.0) + " seconds");
    pool.destroy();
}


(9)需要注意的地方

  • 事務和管道都是非同步模式。在事務和管道中不能同步查詢結果。比如下面兩個呼叫,都是不允許的:

  • Transaction tx = jedis.multi();
     for (int i = 0; i < 100000; i++) {
         tx.set("t" + i, "t" + i);
     }
     System.out.println(tx.get("t1000").get());  //不允許
     
     List<Object> results = tx.exec();
     
     …
     …
     
     Pipeline pipeline = jedis.pipelined();
     long start = System.currentTimeMillis();
     for (int i = 0; i < 100000; i++) {
         pipeline.set("p" + i, "p" + i);
     }
     System.out.println(pipeline.get("p1000").get()); //不允許
     
     List<Object> results = pipeline.syncAndReturnAll();


  • 事務和管道都是非同步的,個人感覺,在管道中再進行事務呼叫,沒有必要,不如直接進行事務模式。

  • 分散式中,連線池的效能比直連的效能略好(見後續測試部分)。

  • 分散式呼叫中不支援事務。

  • 因為事務是在伺服器端實現,而在分散式中,每批次的呼叫物件都可能訪問不同的機器,所以,沒法進行事務。

(10)總結

  • 分散式中,連線池方式呼叫不但執行緒安全外,根據上面的測試資料,也可以看出連線池比直連的效率更好。

  • 經測試分散式中用到的機器越多,呼叫會越慢。


相關推薦

Java的jdbc使用addBatch進行批處理操作方式

方式一、批量執行預定義模式的SQL public static void exeBatch(Connection conn) { try { String sql = "insert into t_example (code, name) values (?,?)";

日期格式化操作方式

由於DateFormat是非執行緒安全的,因此在多執行緒併發情況下日期格式化時需要特別注意。執行緒不安全的處理方式private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH

Android隨筆之——模擬按鍵操作方式

1 package com.lsj.keyboardsample; 2 3 import android.app.Activity; 4 import android.app.Instrumentation; 5 import android.os.Bundle; 6 import andro

C#執行非同步操作方式比較和總結

原文地址:http://www.cnblogs.com/durow/p/4826653.html 轉載此文的目的就是想讓自己記住曾經尋找過這些資料 感謝這位博主的無私奉獻 0x00 引言 之前寫程式的時候在遇到一些比較花時間的操作例如HTTP請求時,總是會new一

jedis操作redis方式

redis是一個著名的key-value儲存系統,也是nosql中的最常見的一種。其實,個人認為,redis最強大的地方不在於其儲存,而在於其強大的快取作用。 我們可以把它想象成一個巨大的(多借點叢集,聚合多借點的記憶體)的Map,也就是Key-Value。 所以,我

彈窗確認操作的業務邏輯與方式

back confirm function 綁定 問題 tor asc all document 首先,我是一名菜雞的前端開發工程師,只會切圖,除開切圖之外 我只有兩個不會,這也不會,那也不會。 最近在做一個後臺管理的項目,我需要做一個功能: 在後臺操作 刪除 修改

redis持久化的方式

但是 工作 http 計算 targe pen 化工 index 數據安全 Redis是一種高級key-value數據庫。它跟memcached類似,不過數據可以持久化,而且支持的數據類型很豐富。有字符串,鏈表,集 合和有序集合。支持在服務器端計算集合的並,交和補集(d

WPFの操作檔案瀏覽框方式

原文: WPFの操作檔案瀏覽框幾種方式 方式1: 使用win32控制元件OpenFileDialog Microsoft.Win32.OpenFileDialog ofd = new Microsoft.Win32.OpenFileDialog(); ofd.DefaultExt

Redis持久化策略(RDB &AOF) redis持久化的方式 1、前言

redis持久化的幾種方式 1、前言 Redis是一種高階key-value資料庫。它跟memcached類似,不過資料可以持久化,而且支援的資料型別很豐富。有字串,連結串列,集 合和有序集合。支援在伺服器端計算集合的並,交和補集(difference)等,還支援多種

[Redis] Redis叢集的方式

  專案中用到Redis,所以準備學習一下,感覺Redis的概念還是很多的,什麼主從模式、sentinel模式、叢集模式的,一下子都暈了,我覺得還是有必要先理清這些基本概念再說。 一、單節點例項   單節點例項還是比較簡單的,平時做個測試,寫個小程式如果需要用到快取的話,啟

redis持久化方式的比較

redis持久化的幾種方式 1、前言 Redis是一種高階key-value資料庫。它跟memcached類似,不過資料可以持久化,而且支援的資料型別很豐富。有字串,連結串列,集 合和有序集合。支援在伺服器端計算集合的並,交和補集(difference)等,

Python檔案操作中的a,a+,w,w+方式的區別 ——轉載

轉載:https://blog.csdn.net/qq_38059635/article/details/81606977   第一步 排除檔案開啟方式錯誤: r只讀,r+讀寫,不建立 w新建只寫,w+新建讀寫,二者都會將檔案內容清零 (以w方式開啟,不能讀出。w+可讀

Python檔案操作中的a,a+,w,w+,rb+,rw+,ra+方式的區別

access_mode:開啟方式,r讀,w寫,a追加,r+ w+ a+ 都是以讀寫方式開啟,rb二進位制讀,wb二進位制寫,rb+ wb+ ab+二進位制讀寫  buffering:預設值  二、對檔案進行操作  將檔案中的內容讀入到一個字串變數/列表中 函式:read(),

【由淺至深】redis 現實發布訂閱的方式

前言 提到訊息佇列,最熟悉無疑是 rabbitmq,它基本是業界標準的解決方案。本文詳細介紹 redis 多種現實輕訂閱方法,作者認為非常有趣並加以總結,希望對有需要的朋友學習 redis 功能有一定的帶入作用。 方法一:SUBSCRIBE + PUBLISH //程式1:使用程式碼現實訂閱端 var s

redis判斷key是否存在(過期)的方式

exist命令 EXISTS key 檢查給定 key 是否存在。 可用版本:>= 1.0.0 時間複雜度:O(1) 返回值: 若 key 存在,返回 1

Python操作excel的方式--xlrd、xlwt、openpyxl

釋出時間:2016-05-13, 17:54:19 最後更新:2016-05-13, 21:29:30 在處理excel資料時發現了xlwt的侷限性–不能寫入超過65535行、256列的資料(因為它只支援Excel 2003及之

樹莓派的GPIO操作方式

轉載出處1、http://www.waveshare.net/study/article-600-1.html2、http://www.waveshare.net/study/article-601-1.htmla)使用shell指令碼方式b)使用sysfs方式,編寫.c檔案

redis 儲存自定義java物件有方式

最近去面試,碰到面試官提問,如果要把一個自定義的java物件儲存到redis中,除了一般使用json和序列化之外,還有一種,可以配置redis的配置檔案,操作hash型別,直接使用HGETALL (或

session存入redis方式

1,int_set('session.save_path',值);2,session.save_path="http"//127.0.0.1:6379?Aath=密碼";3,session_set_save_handler(open,close,read,write,dele

.net操作SQL資料庫中的方式

1:直接操作 省略………. sqlConnection conn = new sqlConnection();  conn.Open(); conn.Close(); 2:通過using直接操作,不用關閉 sqlConnection conn = new sqlConnec