redis list队列如何批量获取?

2 个回答

  • 美啦美啦美啦
    不要在赚钱的路上把健康丢了,要在健康的路上顺便把钱赚了。
    当我们使用Redis队列进行大量数据存取时,RPUSH可以实现一次存入多条数据,而逐条LPOP性能往往不尽如人意。这时就需要批量读取List中的数据再进行处理,减少redis读写次数。幸好redis提供了lrange方法,可以实现list的批量读取。 Java代码如下: ```java public static void main(String[] args) { Jedis jedis = null; String listName = "test"; String redisHost = "localhost"; String redisPwd = "123456"; int redisPort = 6379; int i = 0; Long begin = Calendar.getInstance().getTimeInMillis(); try { List list=new ArrayList(); //获取jedis连接 jedis = JedisUtil.getDataJedis(redisHost, redisPort, redisPwd); while (true) { //从List批量获取数据,每次取200条 list = jedis.lrange(listName,0,199); int num=list.size(); if(num == 0){ Thread.sleep(1000); continue; } System.out.println("从list获取到"+num+"条数据"); //将list做修剪,去掉已经读出的数据 jedis.ltrim(listName,num,-1); i+=num; if (i>10000){ break; } } } catch (Exception e) { e.printStackTrace(); }finally { if (jedis!=null){ jedis.close(); } } Long end = Calendar.getInstance().getTimeInMillis(); System.out.println("读取"+i+"条共耗时:[" + (end-begin)+"]ms"); } ``` 这是使用RPUSH,LPOP的情况,如果是从左端写入的lpush怎么办呢?别急 Lrange还可以从右侧读取,只要把游标改成负数即可,-1即队列最后一条数据。注意标号要从左到右。另外lrange的标号参数都是左右包含的闭区间。 ```java try { List list=new ArrayList(); jedis = JedisUtil.getDataJedis(redisHost, redisPort, redisPwd); while (true) { //从List右侧批量获取数据,每次取200条 list = jedis.lrange(listName,-200,-1); int num=list.size(); if(num == 0){ Thread.sleep(1000); continue; } System.out.println("从list获取到"+num+"条数据"); jedis.ltrim(listName,0,-201); i+=num; if (i>10000){ break; } } } catch (Exception e) { e.printStackTrace(); }finally { if (jedis!=null){ jedis.close(); } } ```
    发布于 2022-03-07 10:49 •IP属地 湖南
    举报
    评论
    收藏

  • 小洋
    纵然前路迷茫,纵然天隔一方,纵然我手中的刀刃已然破碎,也无法阻挡我寻找你的道路。
    一般情况下,从 list 中获取数据可以是 lpop 或者 rpop,每执行一次,如果有数据就返回数据,如果没有就返回空。 在此基础上又有两个优化后的命令 blpop 和 brpop,也是每次只取一条记录,但碰到 list 为空时,就陷入阻塞状态,直到有数据为止。 以上四个命令都是单条记录获取,事实上 redis 还提供了 lrange 和 ltrim 两个命令,可搭配使用使得批量获取 list 中数据。 lrange 返回 list 中指定区间内的元素,区间范围通过偏移量 start 和 end 确定。如往队列 chars 塞入26个英文字母: ```java 127.0.0.1:6379> rpush chars a b c d e f g h i j k l m n o p q r s t u v w x y z (integer) 26 127.0.0.1:6379> llen chars (integer) 26 ``` 如果查看队列 chars 中前 10 条数据: ```java 127.0.0.1:6379> lrange chars 0 9 1) "a" 2) "b" 3) "c" 4) "d" 5) "e" 6) "f" 7) "g" 8) "h" 9) "i" 10) "j" 127.0.0.1:6379> llen chars (integer) 26 ``` 注意,此时虽然能获取到 list 中数据,但是数据并没有从 list 中删除,从执行 llen 命令显示还有 26 条记录也能看出来。这时候就要派上 ltrim 命令了。 ltrim 命令是对一个 list 进行裁剪,只获取指定区间内的元素,区间范围也由偏移量 start 和 end 确定。如果 end 值为 -1,则保留到最后一个元素。 由于已经拿到 list 中前 10 条数据,现在只需要保留从第 11 个元素开始及后面的所有数据。 ```java 127.0.0.1:6379> ltrim chars 10 -1 OK 127.0.0.1:6379> llen chars (integer) 16 127.0.0.1:6379> lrange chars 0 -1 1) "k" 2) "l" 3) "m" 4) "n" 5) "o" 6) "p" 7) "q" 8) "r" 9) "s" 10) "t" 11) "u" 12) "v" 13) "w" 14) "x" 15) "y" 16) "z" ``` 在执行 ltrim 命令后可以看到队列 chars 中只剩下 16 条数据,并且删除的数据恰好就是前面通过 lrange 获取的 10 条数据。 至此就实现了批量获取 redis 队列中数据,相对逐条获取 rpop 和 brpop,效率要高得多。
    发布于 2022-03-05 20:19 •IP属地 安徽
    举报
    评论
    收藏