2016-06-13 26 views
0

我有一個分佈式系統在一個地方我插入約10000項在redis列表中然後調用我的多個應用程序鉤來處理項目。我需要的是有一些ListLeftPop類型的方法與項目的數量。它應該從redis列表中刪除項目並返回到我的調用應用程序。Redis流行列表項目按項目數量

我使用Stackexchange.Resis.extension

我目前的方法只是GET(不是POP)是

public static List<T> GetListItemRange<T>(string key, int start, int chunksize) where T : class 
     { 
      List<T> obj = default(List<T>); 
      try 
      { 
       if (Muxer != null && Muxer.IsConnected && Muxer.GetDatabase() != null) 
       { 
        var cacheClient = new StackExchangeRedisCacheClient(Muxer, new NewtonsoftSerializer()); 
        var redisValues = cacheClient.Database.ListRange(key, start, (start + chunksize - 1)); 
        if (redisValues.Length > 0) 
        { 
         obj = Array.ConvertAll(redisValues, value => JsonConvert.DeserializeObject<T>(value)).ToList(); 
        } 
       } 
      } 
      catch (Exception ex) 
      { 
       Logger.Fatal(ex.Message, ex); 
      } 
      return obj; 
     } 

POP和得到我有找到一個片段

var cacheClient = new StackExchangeRedisCacheClient(Muxer, new NewtonsoftSerializer()); 
        var redisValues = cacheClient.ListGetFromRight<T>(key); 

但它只會做單個項目

+0

所以,你想一下子從列表中流行的所有項目? –

+0

不是所有的,但由一些可配置的號碼。比方說,100一次 –

+0

已嘗試var cacheClient = new StackExchangeRedisCacheClient(Muxer,new NewtonsoftSerializer()); var redisValues = cacheClient.ListGetFromRight (key);但它只會彈出單個項目 –

回答

1

我假設你正在研究一個隊列,您可以在一個位置插入1000個項目,並按照插入順序在多個位置檢索它們。

你不能用一個命令來實現它,但你可以用兩個命令來完成它。你可以寫一個lua腳本來使它們成爲原子。

Lrange:http://redis.io/commands/lrange

Lrange list -100 -1 

這將列出您在列表中的第100個元素。這裏的偏移量是-100。 請注意,這將以與插入順序相反的順序返回項目。所以你需要反轉循環來確保隊列機制。

LTRIM:http://redis.io/commands/ltrim

ltrim list 0 -101 

這將削減在列表中的第一個100個元素。這裏101是n + 1,因此它必須是101.這裏的偏移量是101

將它們寫入lua塊中將確保您的原子性。

讓我給你一個簡單的例子。

您在一個位置插入100個元素。

lpush list 1 2 3 .. 100 

您有多個客戶端 每個試圖訪問這個盧阿塊。說你的n值是5。第一個 客戶端進入並獲得前5個插入的元素。

127.0.0.1:6379> lrange list -5 -1 
1) "5" 
2) "4" 
3) "3" 
4) "2" 
5) "1" 

你讓他們在你的lua對象,並刪除它們。

127.0.0.1:6379> LTRIM list 0 -6 
OK 

他們返回到您的代碼,現在你想要的結果是1 2 3 4 5,但你已經得到的是5 4 3 2 1,所以你需要扭轉的循環和執行操作。

當下一個客戶端進入時,它將獲得下一組值。

127.0.0.1:6379> lrange list -5 -1 
1) "10" 
2) "9" 
3) "8" 
4) "7" 
5) "6" 

以這種方式你可以達到你的要求。希望這可以幫助。

編輯:

的Lua腳本:

local result = redis.call('lrange', 'list','-5','-1') 
redis.call('ltrim','list','0','-6') 
return result 
+0

謝謝Karthikeyan。我的分析是一樣的,我需要兩個命令。我可能需要一個lua腳本來實現它。我將嘗試製作一個可以從ScriptEvaluate調用的單個lua腳本。但我直接從api尋找解決方案而無需使用Lua腳本 –

+0

您可以幫助我爲這些操作組合使用Lua腳本。以前我只有這種腳本的一個經驗,在http://stackoverflow.com/questions/34871567/redis-distributed-increment-with-locking –

0

感謝卡菲基恩。 與Redis的我的C#代碼如下

public static RedisResult PopListItemRange(int chunksize, string key) 
     { 
      RedisResult valreturn = null; 
      try 
      { 

       IDatabase db; 
       if (Muxer != null && Muxer.IsConnected && (db = Muxer.GetDatabase()) != null) 
       { 
        valreturn = db.ScriptEvaluate(@" local result = redis.call('lrange',KEYS[1],ARGV[1], '-1') 
                  redis.call('ltrim',KEYS[1],'0',ARGV[2]) 
            return result", new RedisKey[] { key }, flags: CommandFlags.HighPriority, values: new RedisValue[] { -chunksize, -chunksize - 1 }); 
       } 

      } 
      catch (Exception ex) 
      { 
       Logger.Fatal(ex.Message, ex); 
      } 
      return valreturn; 
     } 

現在只是在做一個調整,當列表爲空刪除Redis的關鍵