【问题标题】:Redis poping multiple elements from a listRedis 从列表中弹出多个元素
【发布时间】:2020-11-13 21:35:49
【问题描述】:

我正在寻找 LPOP 和 LPOPRPUSH 作为弹出值的原子操作的有效选项。 但是我有一项工作,每 2 秒从该列表中弹出 1000 个值 - 这是对 Redis 的 1000 个请求。 我会使用 SPOP,它可以在一个请求中返回 X 值。但那些是随机的,而不是最左边的。 我确实需要从列表的左侧弹出它们。

在没有锁定和原子的情况下,我有哪些最快的选择?我有多个服务器可以访问此列表,但我无法检索重复值(这就是 LRANGE 对我不起作用的原因)

编辑 我越想越觉得需要妥协和使用 SPOP。

场景是使用 Redis 批量插入到数据库中。而不是每秒向 MySQL 插入数千个 - 我正在推送到 Redis,每 2 秒获取值并一次性插入 MySQL。

如果我将时间戳添加到 Redis 中的实际值,我想我可以使用 SPOP,并且为了避免值可能永远卡在集合中的可能性,我将运行 SPOP x 1000 循环直到 null。

【问题讨论】:

  • 您是否考虑过使用事务?完整的事务是原子的和一个请求,但是是顺序执行的多个命令(这可能是您试图避免的,而不是寻找单个命令)
  • 你在multi/exec或lua内部尝试lrangeltrim
  • 我读过这个选项,但没有尝试过,因为我想要一个没有可能失败的简单解决方案(redis 事务中没有回滚)。
  • lrange 将充当readltrim 将充当write/update 并且将按照该顺序进行,因此即使您在读取时失败,它也不会影响写入所以列表不会处于脏状态。
  • 理论上,两个会话可以读取相同的对象吗?

标签: redis redis-cluster


【解决方案1】:

有多种选择:

  1. 使用 Lua 脚本在单个 EVAL 命令中弹出 N 个元素:
EVAL 'local result = {}; for i = 1, ARGV[1] do result[i] = redis.call("lpop", KEYS[1]) end; return result' 1 key N
  1. 使用Redis pipeline发送N条LPOP命令来减少RTT。

【讨论】:

  • 如果中间出现问题并且值已经弹出怎么办?
  • 通常不会失败,除非 Redis 出现 OOM 问题、与 Redis 的连接断开或 Redis 宕机,否则您可能会丢失一些数据。
  • SPOP也有类似的问题。通常你不需要担心这个。
  • 你能说出这三个选项的优势(如果有的话)吗?
  • Lua 脚本保证原子性(客户端获取 1、2、3、...、N 个元素),而管道不保证(客户端可能获取 1、3、6、8... 元素)。这两种方法都保证从列表的左侧弹出元素,而 SPOP 不保证
猜你喜欢
  • 2022-01-06
  • 2019-08-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-07
  • 2018-08-12
  • 2012-03-19
  • 2022-01-23
相关资源
最近更新 更多