2016-06-13 9 views
0

У меня есть распределенная система, в которой в одном месте я вставляю около 10000 элементов в список redis, а затем вызываю мой многократный захват приложений для обработки элементов. мне нужно иметь некоторый тип меток ListLeftPop с количеством элементов. Он должен удалить элементы из списка redis и вернуться к моему вызывающему приложению.Redis Pop list item По номерам позиций

Я использую Stackexchange.Resis.extension

Мой текущий метод только для ГЭТ (не поп) является

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; 
     } 

Для поп-музыки и получить у меня есть найти фрагмент

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 (ключ); но он будет только поп один элемент –

ответ

1

Предполагаю, что вы работаете над queue, где вы вставляете 1000 предметов в одном месте и извлекаете их в нескольких местах в том порядке, в котором оно вставлено.

Вы не можете добиться этого с помощью одной команды, но вы можете сделать это с помощью двух команд. Вы можете написать сценарий lua, чтобы сделать их атомарными.

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

Lrange list -100 -1 

Это перечислит вам первые 100 элементов в списке. здесь смещение равно -100. Обратите внимание, что это вернет элементы в противоположном порядке, в которые он вставлен. Поэтому вам необходимо изменить цикл, чтобы обеспечить механизм очереди.

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

ltrim list 0 -101 

Это обрежет 1-й 100 элементов в списке. здесь 101 равно n + 1, поэтому оно должно быть 101. Здесь смещение равно 101

Написание их в блоке lua обеспечит вам атомарность.

Позвольте мне привести простой пример.

Вы вставляете 100 элементов в одном месте.

lpush list 1 2 3 .. 100 

У вас есть несколько клиентов каждых пытаются получить доступ к этой Lua блока. Скажем, ваше значение n здесь 5. 1-й клиент входит и получает первые 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" 

Таким образом, вы можете достичь своего требования. Надеюсь это поможет.

EDIT:

Lua скрипт:

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

Спасибо, Karthikeyan. Мой анализ был таким же, что мне нужны две команды. И мне может понадобиться один сценарий lua для его достижения. Я попытаюсь сделать этот единственный сценарий lua, который я могу вызвать из ScriptEvaluate. Но я искал решение прямо из api без необходимости сценария Lua. –

+0

Можете ли вы помочь мне в объединенном сценарии Lua для этих операций. Раньше у меня был только один опыт такого сценария по адресу http://stackoverflow.com/questions/34871567/redis-distributed-increment-with-locking –

0

Благодаря Картикеян. Мой C# код с Redis заключается в следующем

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 Key