使用 EVAL、SCAN 和 DEL 的 Redis 通配符删除脚本返回“非确定性命令后不允许写入命令”

2024-04-09

因此,我正在寻求构建一个 lua 脚本,该脚本使用 SCAN 根据模式查找键并删除它们(原子地)。我首先准备了以下脚本

local keys = {};
local done = false;
local cursor = "0"
repeat
    local result = redis.call("SCAN", cursor, "match", ARGV[1], "count", ARGV[2])
    cursor = result[1];
    keys = result[2];
    for i, key in ipairs(keys) do
        redis.call("DEL", key);
    end
    if cursor == "0" then
        done = true;
    end
until done
return true;

这会吐出以下“错误:@user_script:9:在非确定性命令后不允许写入命令”所以我想了一下并想出了以下脚本:

local all_keys = {};
local keys = {};
local done = false;
local cursor = "0"
repeat
    local result = redis.call("SCAN", cursor, "match", ARGV[1], "count", ARGV[2])
    cursor = result[1];
    keys = result[2];
    for i, key in ipairs(keys) do
        all_keys[#all_keys+1] = key;
    end
    if cursor == "0" then
        done = true;
    end
until done
for i, key in ipairs(all_keys) do
    redis.call("DEL", key);
end
return true;

仍然返回相同的错误(@user_script:17:在非确定性命令之后不允许写入命令)。这让我难住了。有什么办法可以规避这个问题吗?

脚本是使用 phpredis 和以下内容运行的

$args_arr = [
          0 => 'test*',   //pattern
          1 => 100,     //count for SCAN
  ];
  var_dump($redis->eval($script, $args_arr, 0));

UPDATE:以下内容适用于 Redis 3.2 及以下版本。从该版本开始,基于效果的复制解除了对非决定论的禁令,因此所有的赌注都将被取消(或者更确切地说,将被取消)。

你不能(也不应该)混合SCAN命令族与脚本中的任何写入命令都是如此,因为前者的回复取决于内部 Redis 数据结构,而这些数据结构又对于服务器进程来说是唯一的。换句话说,两个 Redis 进程(例如主进程和从属进程)不能保证返回相同的回复(因此在 Redis 复制上下文中[这不是操作,而是基于语句],这会破坏它)。

Redis 尝试通过阻止任何写入命令(例如DEL)如果它是在随机命令之后执行的(例如SCAN但是也TIME, SRANDMEMBER和类似)。我确信有办法解决这个问题,但是你想这样做吗?请记住,您将进入未知领域,其中系统的行为未定义。

相反,接受这样一个事实:您不应该混合随机读取和写入,并尝试考虑一种不同的方法来解决您的问题,即根据模式以原子方式删除一堆键。

首先问问自己是否可以放宽任何要求。它必须是原子的吗?原子性意味着 Redis 在删除期间将被阻塞(无论最终实现如何),并且操作的长度取决于作业的大小(即被删除的键的数量及其内容[删除一个大集合是例如,比删除短字符串更昂贵])。

如果原子性不是必须的,则定期/惰性地SCAN并小批量删除。如果这是必须的,请理​​解您基本上是在尝试模仿evil KEYS命令 :) 但如果您事先了解该模式,您可以做得更好。

假设该模式在应用程序运行时已知,您可以收集相关键(例如在集合中),然后使用该集合以原子和复制安全的方式实现删除,这比遍历整个键空间更有效。

然而,最“困难”的问题是,如果您需要在确保原子性的同时运行临时模式匹配。如果是这样,问题归结为获取键空间的按模式过滤快照,然后立即进行一系列删除(再次强调:当数据库被阻止时)。在这种情况下你可以很好地使用KEYS在你的 Lua 脚本中并希望得到最好的结果......(但充分了解你可能会求助于SHUTDOWN NOSAVE很快:P)。

最后的优化是对键空间本身进行索引。两个都SCAN and KEYS基本上都是全表扫描,那么如果我们对该表建立索引呢?想象一下,在事务期间可以查询的键名称上保留索引 - 您可能可以使用排序集和字典范围(HT@TwBert)消除了大部分模式匹配需求。但代价高昂……您不仅需要进行双重簿记(将每个密钥的名称成本存储在 RAM 和 CPU 中),而且还被迫增加应用程序的复杂性。为什么要增加复杂性?因为要实现这样的索引,您必须自己在应用程序层(可能还包括所有其他 Lua 脚本)中维护它,小心地将每个对 Redis 的写入操作包装在一个事务中,该事务也会更新索引。

假设您完成了所有这些(并考虑到明显的陷阱,例如增加的复杂性可能导致错误、Redis、RAM 和 CPU 上的写入负载至少加倍、扩展限制等等......)您可以拍拍自己庆幸自己以一种不符合 Redis 设计初衷的方式使用了 Redis。虽然即将推出的 Redis 版本可能(或可能不)包含针对这一挑战的更好解决方案(@TwBert - 想要联合 RCP/contrib 并再次破解 Redis 吗?),在尝试此操作之前,我强烈建议您重新考虑最初的要求并验证您是否正确使用 Redis(即根据您的数据访问需求设计您的“架构”)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 EVAL、SCAN 和 DEL 的 Redis 通配符删除脚本返回“非确定性命令后不允许写入命令” 的相关文章

  • redis集群不断打印日志WSA_IO_PENDING

    当我启动redis集群的所有redis服务器时 所有这些服务器不断打印类似WSA IO PENDING clusterWriteDone的日志 9956 03 Feb 18 17 25 044 WSA IO PENDING writing
  • 了解静态链接嵌入式lua环境中lua扩展dll的构建/加载

    我有一个相对复杂的 lua 环境 我试图了解以下内容如何工作 起始设置包括以下两个模块 主要应用 无lua环境 DLL 静态链接到lua lib 包括解释器 该 dll 被加载到主应用程序中 并运行 lua 控制台解释器和可从控制台访问的
  • 如何在节点redis客户端上设置读取超时?

    在 github 上我没有看到读取超时的选项 https github com NodeRedis node redis https github com NodeRedis node redis There s connect timeo
  • 如何设置 Celery 以通过 ssl 与 Azure Redis 实例对话

    使用 的伟大答案 如何在microsoft azure上的django项目中配置celery redis https stackoverflow com questions 39616701 how to configure celery
  • 循环直到在表中找到 2 个特定值?

    我试图找到一种更聪明的方法来解决这个问题 这是与游戏相关的代码的摘录 它循环遍历每个背包的每个插槽 直到找到铲子和绳子 local continue local foundShovel foundRope for i 0 Container
  • Lua 中的内联条件(a == b ? "yes" : "no")?

    无论如何 Lua 中可以使用内联条件吗 Such as print blah a true blah nahblah Sure print blah a and blah or nahblah
  • 在 Corona sdk 上保存高分?

    我想保存游戏中创建的高分 并且当玩家点击高分按钮时可以在主菜单中看到 有人可以帮助我吗 您可以使用SQLITE https docs coronalabs com api library sqlite3 index html将高分保存到数据
  • 如果另一个键中的计数器低于零,则从集合中原子删除一个项目?

    雷迪斯2 0 3 在我的 Redis DB 中 我有一组项目 每个项目都有一个与其关联的计数器 MULTI SADD items set foo INCRBY items foo 10000 EXEC 新项目会以随机间隔添加到集合中 当用户
  • Redis INCRBY 有限制

    我想知道是否有一种方法可以通过我的应用程序的单次往返在 Redis 中执行此操作 对于给定的键K 其可能值V是范围内的任意整数 A B 基本上 它有上限和下限 When an INCRBY or DECRBY发出命令 例如INCRBY ke
  • 从redis中检索大数据集

    一台服务器上的应用程序查询另一台服务器上运行的 Redis 查询的结果数据集约为 250kzrangebyscore objects locations inf inf这在应用程序服务器上似乎需要 40 秒 当使用命令执行时redis cl
  • 什么时候适合使用Lua这样的嵌入式脚本语言

    我玩 魔兽世界 大约有两年了 我对用来编写插件的 Lua 很好奇 由于到目前为止我读到的有关 Lua 的内容都是 快 轻 和 这太棒了 所以我想知道如何以及何时使用它 您需要在系统中嵌入像 Lua 这样的脚本语言的典型情况是什么 当您需要最
  • 如何在 Lua 中实现 OO?

    Lua 没有内置对 OO 的支持 但它允许您自己构建它 您能否分享一些实现面向对象的方法 请为每个答案写一个例子 如果您有更多示例 请发布另一个答案 我喜欢将 OOP 视为容器 对象 内的数据封装以及可以使用该数据完成的操作子集 还有很多内
  • 确定已编译Lua的编译器版本

    我有一些已编译的 LuaQ 我需要确定用于编译它的确切版本 有什么可能的方法吗 编译的脚本在文件开头有一个标头 4 bytes signature x1bLua 1 byte version 0x51 1 byte format 1 byt
  • 使用 FastCGI 运行 Lua 脚本

    我目前正在尝试找出使用 FastCGI 与 lighttpd 或 Nginx 一起运行 Lua 脚本的方法 我唯一能挖到的是WSAPI http keplerproject github com wsapi 开普勒计划的一部分 但我想知道是
  • lua中的权限问题

    是否需要在 corona build settings 中设置一些特定权限才能将高分永久保存在文件中 每次运行代码时都会出现 权限被拒绝 的错误 如何纠正这个错误 这是我尝试过的代码 function read score local f1
  • VB6 - Lua 集成

    我想知道是否有人有任何集成 Lua 和 VB6 的技巧 我正在运行一个小型在线角色扮演游戏 添加一些脚本会很棒 嗯 这是可行的 我曾经为 Lua 5 0 2 做过 但找不到文件 在您拥有的选项中 您可以 将 Lua 封装在公开 Lua AP
  • 使用 Sentinels 升级 Redis 的最佳实践?

    我有 3 个 Redis 节点 由 3 个哨兵监视 我进行了搜索 文档似乎不清楚如何最好地升级此类配置 我目前使用的是 3 0 6 版本 我想升级到最新的 5 0 5 我对这方面的程序有几个疑问 升级两个大版本可以吗 我在我们的暂存环境中执
  • 有没有办法用Lettuce自动发现Redis集群中新的集群节点IP

    我有一个Redis集群 3主3从 运行在一个库伯内斯簇 该集群通过Kubernetes 服务 Kube 服务 我将我的应用程序服务器连接到 Redis 集群 使用Kube 服务作为 URI 通过 Redis 的 Lettuce java 客
  • Spring Data JPA Redis:无法编写基于自定义方法的查询

    我已经使用 Redis 配置了 Spring Data JPA 并使用RedisRepositorieswith 提供了类似的方法find findAll 所有这些方法似乎都工作得很好 但我无法编写我的自定义方法 RedisEntity f
  • Redis是如何实现高吞吐量和高性能的?

    我知道这是一个非常普遍的问题 但是 我想了解允许 Redis 或 MemCached Cassandra 等缓存 以惊人的性能极限工作的主要架构决策是什么 如何维持连接 连接是 TCP 还是 HTTP 我知道它完全是用C写的 内存是如何管理

随机推荐

  • 如何使用java删除文本文件中的特定字符串?

    我的输入文件有很多记录 作为示例 我们假设它有 这里的行号仅供参考 1 end 2 endline 3 endofstory 我期望我的输出为 1 2 endline 3 endofstory 但是当我使用这段代码时 import java
  • 将 Azure Functions 升级到 5.0:System.UriFormatException

    我一直致力于将我们的 Azure Functions 实现之一升级到 net 5 我已经与许多恶魔作斗争了 但正当我以为我已经整理了所有配置和依赖项注入更改时 它向我抛出了一个曲线球 后host RunAsync in Main 我得到以下
  • GWT CellTable 以编程方式选择 CheckBoxCell

    我有一个带有 CheckBoxCell 列的 cellTable 我想做的是在单元格表之外有一组按钮 让用户自动检查 取消检查一组不同的元素 例如检查所有 取消检查所有 但我想要更复杂的规则 我不明白的是如何访问该元素 我想通过行 列值 并
  • 为什么我没有从 Google OAuth 请求收到 RefreshToken?

    我正在尝试将 Google 日历集成到我的应用程序中 但在传递 RefreshToken 的 OAuth 授权方面遇到一些问题 我收到的 AccessToken 没有问题 但 RefreshToken 属性为 null 请参阅标记为 ERR
  • 用于处理 win32 FILETIME 的 Java 库?

    是否有任何 Java 库可以处理 win32文件时间 http msdn microsoft com en us library ms724284 28v vs 85 29 aspx时间间隔 它基本上是自 1601 年 1 月 1 日以来以
  • 3 个流体 Div 宽度 2 个固定边距?

    我有以下设置 但是将 div 的宽度设置为 30 左右并不能始终如一地工作 一旦窗口宽度小于某个数字 第三个 div 就会低于某个数字 有没有更好的方法来做到这一点 以便我的 div 始终保持内联并不断变得越来越小 同时它们之间的边距保持固
  • 用于 C++ 的 FastCGI

    我只找到了两个用于 C 的 FastCGI 库 有的是 官方 一 http www fastcgi com drupal node 6 q node 21 and 快速cgi https savannah nongnu org projec
  • 用户可编辑带有友好 ID 的 slugs

    Case 我的站点表单包含一个 slug 字段 如果输入了值 则应将其用作 slug 编辑 一些澄清 我想要的很像 slugs 在 WordPress 中的工作方式 如果未提供 slug gt slug 名称 如果提供了 slug gt 使
  • 如何有效检测逻辑和物理处理器的数量?

    目前我正在使用这个功能 它工作正常 但每个查询大约需要 1 秒 所以就我而言 我在应用程序中浪费了 3 秒钟 目前我正在考虑使用 3 个线程在一秒钟内获取所有信息 function GetWMIstring wmiHost wmiClass
  • Smalltalk:原语是如何实现的?

    我知道一切都是对象 您可以向 Smalltalk 中的对象发送消息来执行几乎所有操作 现在我们如何实现一个对象 内存表示和基本操作 来表示原始数据类型 例如如何 对于整数的实现 我查看了 Smalltalk 的源代码并发现了这个Smalli
  • Request.IsAuthenticated 始终为 true。我错过了什么?

    我正在尝试将用户名添加到 cookie 并在注销时清除它 但是Request IsAuthenticated返回始终为 true 因此我无法知道它是否是下一页上的成员 这是我正在尝试的 public void Logout FormsAut
  • 如何修复“向客户端发送响应时失败(22:无效参数)”

    使用 directio 时 如果有多个扇区大小不同的挂载点 Nginx 无法读取文件 我们的服务器在 Nginx 的根文件夹下安装了不同的硬盘 我们所有的旧磁盘的扇区大小都是 512 当我们更换磁盘时 Nginx 突然无法从该磁盘读取文件
  • 在 Android 设备中使用 ACTION_PICK 意图仅显示电话号码联系人

    我的目标是仅向用户显示带有电话号码的联系人 并让用户选择我想在本地存储的几个联系人 我在下面的方法中使用了各种选项来代替 ContactsContract Contacts CONTENT URI 但我收到了很多显示的联系人 许多都是垃圾邮
  • 查找 Java 类文件版本之间的差异

    我正在使用来自商业供应商的大型 Java Web 应用程序 我从供应商那里收到了一个新的 class 文件形式的补丁 该文件应该可以解决我们在软件方面遇到的问题 过去 应用该供应商的补丁会导致出现新的且完全不相关的问题 因此我想在将其应用于
  • 使用端点原型数据存储时设置父键但不设置子键

    如何为 EndpointsModel 设置父级 祖先并让数据存储区自动生成实体 ID 密钥 我已经尝试去适应带有祖先的键 http endpoints proto datastore appspot com examples keys wi
  • Lighttable,设置字体大小

    我是 Light Table IDEAS 的新手 有谁知道如何设置workspace和 Windows 字体大小 我可以更改编辑器字体大小 但不知道如何设置font size对于其他元素 或者更改所有 IDE 字体的全局字体大小 打开命令窗
  • DateTime.TryParseExact 未按预期工作

    谁能解释为什么以下代码片段返回 true 根据文档 d 自定义格式说明符 http msdn microsoft com en us library 8kb3ddd4 aspx dSpecifier 一位数日期的格式不带前导零 那么 当我给
  • Pyparsing - 匹配最外面的一组嵌套括号

    我正在尝试使用 pyparsing 构建一个解析器 该解析器将匹配任意嵌套的括号内的所有文本 如果我们考虑这样的字符串 A B C D E F G Random Middle text H I J 我想要的是解析器以返回两个匹配的方式进行匹
  • 地图在移动设备上显示错误(使用 JQuery mobile)

    我正在使用 jQuery mobile 并且必须显示一些地图 我使用的功能是每次单击特定链接时都会创建地图 但在生成第一个地图后 其他地图显示错误 这里有一个例子 第一张地图 其他地图 我使用这样的函数 function buildMap
  • 使用 EVAL、SCAN 和 DEL 的 Redis 通配符删除脚本返回“非确定性命令后不允许写入命令”

    因此 我正在寻求构建一个 lua 脚本 该脚本使用 SCAN 根据模式查找键并删除它们 原子地 我首先准备了以下脚本 local keys local done false local cursor 0 repeat local resul