Redis Pop列表项目按项目数量

时间:2016-06-13 04:24:28

标签: c# caching redis stackexchange.redis .net-4.5.2

我有一个分布式系统,在一个地方我在redis列表中插入大约10000个项目然后调用我的多个应用程序挂钩来处理项目。我需要的是有一些ListLeftPop类型的methhod与项目数量。它应该从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和get我找到了一个片段

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

但它只适用于单品

2 个答案:

答案 0 :(得分:2)

我假设您正在使用队列,您可以在一个地方插入1000个项目,然后按照插入顺序在多个地方检索它们

您无法通过单个命令实现它,但您可以使用2个命令来完成它。你可以编写一个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
  

您有多个客户   每个人都试图访问这个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"

通过这种方式,您可以实现您的要求。希望这可以帮助。

修改

Lua脚本:

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

答案 1 :(得分:0)

谢谢Karthikeyan。 我的带有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 Key