Redis 弹出列表项按项数 [英] Redis Pop list item By numbers of items

查看:40
本文介绍了Redis 弹出列表项按项数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个分布式系统,在一个地方,我在一个 redis 列表中插入了大约 10000 个项目,然后调用我的多个应用程序挂钩来处理项目.我需要的是有一些 ListLeftPop 类型的方法和项目数.它应该从 redis 列表中删除项目并返回到我的调用应用程序.

我正在使用 Stackexchange.Resis.extension

我目前仅用于 get(不是 pop)的方法是

 公共静态列表GetListItemRange(string key, int start, int chunksize) 其中 T : 类{列表obj = default(List);尝试{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));如果(redisValues.Length > 0){obj = Array.ConvertAll(redisValues, value => JsonConvert.DeserializeObject(value)).ToList();}}}捕获(异常前){Logger.Fatal(ex.Message, ex);}返回对象;}

对于流行音乐,我找到了一个片段

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

但它只对单个项目有效

解决方案

我假设您正在处理一个队列,您在一个位置插入 1000 个项目并在多个位置检索它们按照插入的顺序.

你不能用一个命令来实现它,但你可以用 2 个命令来实现.您可以编写一个 lua 脚本使它们具有原子性.

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

Lrange list -100 -1

这将列出列表中的前 100 个元素.这里的偏移量为-100.请注意,这将返回与插入顺序相反的项目.所以需要逆循环来保证队列机制.

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

ltrim 列表 0 -101

这将修剪列表中的第 100 个元素.这里的 101 是 n+1 所以它一定是 101.这里的偏移量是 101

将它们写在 lua 块中将确保您的原子性.

让我举个简单的例子.

<块引用>

您在一个地方插入了 100 个元素.

lpush 列表 1 2 3 .. 100

<块引用>

您有多个客户每个都试图访问这个 lua 块.在这里假设您的 n 值为 5.第一客户端进入并插入前 5 个元素.

127.0.0.1:6379>lrange列表 -5 -11)5"2)4"3)3"4)2"5)1"

<块引用>

您将它们保留在 lua 对象中并删除它们.

127.0.0.1:6379>LTRIM 列表 0 -6好的

将它们返回到您的代码中,现在您想要的结果是 1 2 3 4 5 但您得到的是 5 4 3 2 1.因此您需要反转循环并执行操作.

当下一个客户进来时,它将获得下一组值.

127.0.0.1:6379>lrange列表 -5 -11)10"2)9"3)8"4)7"5)6"

这样您就可以达到您的要求.希望这可以帮助.

Lua 脚本:

local result = redis.call('lrange', 'list','-5','-1')redis.call('ltrim','list','0','-6')返回结果

I have a distributed system where In one place i insert around 10000 items in a redis list then Call my multiple applications hook to process items. what i need is to Have some ListLeftPop type of methhod with numbers of items. It should remove items from the redis List and return to my calling application.

I am using Stackexchange.Resis.extension

My current method just for get (not pop) is

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

For Pop and get i have find a snippet

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

But it will only do for single item

解决方案

I assume that you are working on a queue, where you insert 1000 items at a single place and retrieve them at multiple place in the order at which it is inserted.

You can't achieve it with a single command but you can do it with 2 commands. You can write a lua script to make them atomic.

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

Lrange list -100 -1

This will list you first 100 elements in the list. here the offset is -100. Note that this will return the items in the opposite order at which it is inserted. So you need to reverse the loop to ensure the queue mechanism.

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

ltrim list 0 -101

This will trim the 1st 100 elements in the list. here 101 is n+1 so it must be 101. Here offset is 101

Writing them inside a lua block will ensure you the atomicity.

Let me give you a simple example.

You insert 100 elements in a single place.

lpush list 1 2 3 .. 100

You have multiple clients each trying to access this lua block. Say your n value is 5 here. 1st client gets in and gets first 5 elements inserted.

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

You keep them in your lua object and delete them.

127.0.0.1:6379> LTRIM list 0 -6
OK

return them to your code, now the result you want is 1 2 3 4 5 but what you have got is 5 4 3 2 1. So you need to reverse the loop and perform the operation.

When the next client comes in it will get the next set of values.

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

In this way you can achieve your requirement. Hope this helps.

EDIT:

Lua script:

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

这篇关于Redis 弹出列表项按项数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆