1. 程式人生 > >redis列表型別list如何一次返回多個值並刪除這些值

redis列表型別list如何一次返回多個值並刪除這些值

redis的列表型別list是一個常用的資料型別,但是這個型別並不支援一次性返回多個值並刪除這些已經返回的值。

其實我們可以通過redis的事務,來完成這個一次性返回多個值並刪除這些已經返回的值的需求。

redis中的事務就是一組命令的集合,這些命令要麼全部執行,要麼全都不執行。redis事務的原理就是一次性將命令都發給服務端,

當服務接收到exec命令之後,按照事務中命令的順序依次執行事務中的命令。exec命令的返回值就是事務中依次執行的命令返回值的集合,返回值的順序和命令的執行順序相同。如果在傳送exec命令前,客戶端和服務端失去連線,這時redis會清空這個事務佇列。

介紹完這些原理,我們再來看看如何完成一次性返回多個值並刪除這些已經返回的值的

需求。

我們這裡要利用兩個列表型別的命令:lrange和ltrim

lrange key start end // 從左邊依次返回key的[start,end] 的所有值,注意返回結果包含兩端的值。

ltrim  key  start end //刪除指定索引之外的所有元素,注意刪除之後保留的元素包含兩端的start和end索引值。

我們這裡舉例測試:


我們構造了一個名為yujie_list的列表型別資料結構,從左邊依次壓入:0 1 2 3 4 5 6 7 8 9

最後從左到右依次列出列表中的所有元素如上圖所示。

接下來我們測試lrange和ltrim命令如下圖:


我們使用lrange yujie_list 0 3命令,從左到右依次列出從索引0到索引3的元素,注意包含了索引0 值為9和索引3值為6的元素。

我們使用ltrim yujie_list 4 -1命令,刪除索引4到最右端之外的所有元素,注意刪除的元素不包含索引4職位5的元素。

好了原理講完了,接下來我們上程式碼:

RedisUtil是一個工具類,用於連線redis服務端。

/**
 * 連線redis服務的工具類
 * @author yujie.wang3
 *
 */
public final class RedisUtil {
    
    //Redis伺服器IP
    private static String ADDR = "10.4.36.93";
    
    //Redis的埠號
    private static int PORT = 6379;
   
    
    //可用連線例項的最大數目,預設值為8;
    //如果賦值為-1,則表示不限制;如果pool已經分配了maxActive個jedis例項,則此時pool的狀態為exhausted(耗盡)。
    private static int MAX_ACTIVE = 100;
    
    //控制一個pool最多有多少個狀態為idle(空閒的)的jedis例項,預設值也是8。
    private static int MAX_IDLE = 20;
    
    //等待可用連線的最大時間,單位毫秒,預設值為-1,表示永不超時。如果超過等待時間,則直接丟擲JedisConnectionException;
    private static int MAX_WAIT = 10000;
    
    private static int TIMEOUT = 10000;
    
    //在borrow一個jedis例項時,是否提前進行validate操作;如果為true,則得到的jedis例項均是可用的;
    private static boolean TEST_ON_BORROW = true;
    
    private static JedisPool jedisPool = null;
    
    /**
     * 初始化Redis連線池
     */
    static {
        try {
            JedisPoolConfig config = new JedisPoolConfig();
            config.setMaxActive(MAX_ACTIVE);
            config.setMaxIdle(MAX_IDLE);
            config.setMaxWait(MAX_WAIT);
            config.setTestOnBorrow(TEST_ON_BORROW);
            jedisPool = new JedisPool(config, ADDR, PORT);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 獲取Jedis例項
     * @return
     */
    public synchronized static Jedis getJedis() {
        try {
            if (jedisPool != null) {
                Jedis resource = jedisPool.getResource();
                return resource;
            } else {
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    
    /**
     * 釋放jedis資源
     * @param jedis
     */
    public static void returnResource(final Jedis jedis) {
        if (jedis != null) {
            jedisPool.returnResource(jedis);
        }
    }
}

測試類如下:
/**
 * 一次返回多個列表值並刪除返回值測試類
 * @author yujie.wang
 *
 */
public class RedisTest {

	public static void main(String[] args) {
		String key = "yujie_test_list";
		initList(key,9);
		printList(key,"原始列表資料");
		List<String> listResult = getListMultValueAfterDel(key,0,3);
		System.out.println("一次返回並刪除資料:"+listResult.toString());
		printList(key,"刪除之後列表資料");
	}
	
	public static void initList(String key,int maxValue){
		Jedis client = RedisUtil.getJedis();
		for(int i = 0;i <= maxValue; i++){
			client.lpush(key, String.valueOf(i));
		}
		System.out.println("初始化列表:"+ key + "完畢");
	}
	
	public static void printList(String key,String message){
		Jedis client = RedisUtil.getJedis();
		List<String> list = client.lrange(key, 0, -1);
		System.out.println(message+ " : " + list.toString());
	}
	
	@SuppressWarnings("unchecked")
	public static List<String> getListMultValueAfterDel(String key,int start, int end){
		List<Object> list = null;
		List<String> listStr = new ArrayList<String>();
		try {		
			Jedis jedis = RedisUtil.getJedis();
			Transaction ts = jedis.multi();
			ts.lrange(key, start, end);
			ts.ltrim(key, end+1, -1);
			list = ts.exec();
			RedisUtil.returnResource(jedis);
		} catch (Exception e) {
			// TODO: handle exception
			System.out.println(e);
		}
		if(list != null && !list.isEmpty()){
			try {
				//獲得命令lrange(key, start, end)的返回結果
				listStr =  (ArrayList<String>)list.get(0);	
			} catch (Exception e) {
				// TODO: handle exception
				System.out.println(e);
			}			
		} else {
			return Collections.emptyList();
		}
		return listStr;
	}
	
}	

輸出結果:


相關推薦

redis列表型別list如何返回刪除這些

redis的列表型別list是一個常用的資料型別,但是這個型別並不支援一次性返回多個值並刪除這些已經返回的值。 其實我們可以通過redis的事務,來完成這個一次性返回多個值並刪除這些已經返回的值的需求。 redis中的事務就是一組命令的集合,這些命令要麼全部執行,要麼全都

下載文件

itl cnblogs script log logs html 文件 download nload 一次下載多個文件 JavaScript多文件下載一次下載多個文件

(轉)Spring文件上傳,包括選中文件

bmi while .html span cto input 獲取文件 dex asn 背景: http://www.cnblogs.com/lixuwu/p/8495275.html已經實現了單文件的上傳和下載,多文件的上傳是另一種情景,這裏記錄下來 實現過程

下載檔案的解決思路-JS

一次下載多個檔案的解決思路(iframe) - Eric 真實經歷 最近開發專案需要做檔案下載,想想挺簡單的,之前也做過,後臺提供下載介面,前端使用window.location.href就行了唄。不過開發的時候發現,有些檔案有附屬檔案,點選 下載按鈕 需要下載兩個檔案,而且不能使用壓縮包的形式。想想

maven 打包maven專案

maven 一次打包多個maven專案。 使用場景 一個專案由多個子專案組成,每個子專案也是一個maven專案。每次打包需要打包每個子專案,很麻煩,其實可以通過配置一個頂級的pom.xml檔案來解決這個問題,只需要打包頂層的maven專案,即可。如果一個專案有多個子專案的pom.

WEB版選擇檔案進行批量上傳(swfupload)的解決方案

功能完全支援ie和firefox瀏覽器!       一般的WEB方式檔案上傳只能使用FileUpload控制元件進行一個檔案一個檔案的進行上傳,就算是批量上傳,也要把檔案一個一個的新增到頁面,無法如windows程式一樣,一次選擇多個檔案進行批量上傳。這樣在某些應用上就

Android6.0及以上版本請求許可權的處理方式

final private int REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS = 124; private void insertDummyContactWrapper() { List<Stri

Android 仿PC端QQ自由截圖,可支援區域

仿PC端QQ截圖,可任意截圖,這裡只做了矩形這一種形狀,可同時支援擷取多個區域,支援撤銷上次截圖,重新擷取。 實現原理: 自定義SurfaceView,在SurfaceView上繪製具有一個可拉伸,移動的矩形框,當點選截圖按鈕後,計算矩形

Ubuntu系統編寫shell指令碼程式安裝軟體包

#!/bin/sh sudo apt-get install gcc g++ python -y sudo apt-get install gcc g++ python python-dev -y sudo apt-get install mercurial -y sudo apt-get install b

使用JDBC插入表、條記錄

程式碼如下: public static void insertBatch() { int count[]; int count1[]; Boolean isinsert = false; Connection con = null; PreparedS

Android 6.0動態申請許可權(申請

Android一次申請多個動態許可權 昨天做一個錄音功能的程式,發現在開啟Mic的時候發生了程式崩潰,但是錯誤提示裡面居然沒有提示許可權禁止。  解決的方法有:1.手動去選擇“應用”–>“程式”–>找到那個程式新增許可權,後面程式就可以正常使用了 2.設定動態請

訓練得到模型做整合的方法

參考論文 SNAPSHOT ENSEMBLES: TRAIN 1, GET M FOR FREE 解決的問題 多個分類器整合可以獲得超過單個分類器的效果,但整合分類器就要求有多個分類器,在訓練速度和測試速度方面不佔優勢。本文提出的方法可以提高整合學習的訓練速度,通過一次訓練,

Python中讀取

Python 2裡面讀取輸入的函式是raw_input(), Python 3的是input(),讀入一個值後回車讀取輸入就退出了,想要一次讀取多個輸入,可以像下面這樣: a, b = raw_inp

如何用shell讀取檔案內容

在寫shell指令碼的時候,因為shell本身的資料結構很簡單,連二維陣列都不能支援,所以配置檔案的形式也不能過於複雜(個人看法,有什麼意見請說),因此需要寫多個配置檔案來滿足業務。 通常情況下,我們用shell讀取一個配置檔案是這樣寫的: while re

WEB版選擇檔案進行批量上傳(Plupload)的解決方案

/// <summary> /// uploadFiles 的摘要說明 /// </summary> public class uploadFiles : IHttpHandler { public void Process

AndroidStudio

功能背景: 因公司專案要求,每次打包都需要打包三個版本,兩個測試版本和一個線上的版本, 並且呼叫不同的baseURL,最開始的做法是每次打包一次就換一個baseURL,然後一個個打包,分別需要打包三次,如果編譯很慢會浪費了很多時間,還需要註釋掉不同的baseUR

替換詞,批量替換字串(使用不了的解決辦法)

三天前上CSDN,發現有人回覆批量替換多個詞的工具使用不了。下載下來試用了一下,確實報錯,這兩天打算做個網頁版本的,排版佈局還沒弄好。 上貼回覆以前工具使用不了的解決辦法:下載32位的jre,然後配置JAVA_HOME。 2、下載完畢解壓後,假如路徑(自

如何銷燬Activity,和如何銷燬activity

public class ActivityCollector { public static List<Activity> activities = new ArrayList<Activity>(); public static void addActivity(

在JDBC插入表、條記錄

{   con = getCon();   con.setAutoCommit(false);                                   // 需要用到事務,不能讓他自動提交,需要手動提交   pst = con.prepareStatement(INSERT_SQL);      

Linux命令基礎34-如何在一個終端執行命令

首先,你是否考慮過,在輸入多個命令後,敲擊回車,希望這多個命令都被執行。其實linux是允許這樣做的。 1. 採用分號(;)分隔多個命令 2. 採用兩個連線符(&&) 3.如果命