草庐IT

Redis:为什么 Lua 脚本要取代事务?

coder 2023-07-17 原文

交易文档说:

"we may deprecate and finally remove transactions" and "everything you can do with a Redis transaction, you can also do with a script"

http://redis.io/topics/transactions

但是真的吗?我发现这有问题。

在一个事务中,您可以 WATCH 多个变量,读取这些变量,并且根据这些变量的独特状态,您可以在调用 EXEC 之前进行一组完全不同的写入。如果在此期间有任何干扰这些变量的状态,EXEC 将不会执行事务。 (允许您重试。这是一个完美的交易系统。)

EVAL 脚本不会让您这样做。根据此页面上的文档:

"Scripts as pure functions...The script always evaluates the same Redis write commands with the same arguments given the same input data set. Operations performed by the script cannot depend on any hidden (non explicit) information or state that may change as script execution proceeds or between different executions of the script, nor can it depend on any external input from I/O devices."

http://redis.io/commands/eval

我在 EVAL 中看到的问题是您无法在脚本中获取这些变量的状态,也无法根据这些变量的状态进行一组独特的写入。再次:“在给定相同的输入数据集的情况下,脚本总是使用相同的参数评估相同的 Redis 写入命令。”所以结果写入已经确定(从第一次运行缓存)并且 EVAL 脚本不关心脚本中的 GET 值是什么。您唯一可以做的就是在调用 EVAL 之前对这些变量执行 GET,然后将这些变量传递给 EVAL 脚本,但问题是:现在调用 GET 和调用 EVAL 之间存在原子性问题。

换句话说,您为交易完成 WATCH 的所有变量,在 EVAL 的情况下,您需要获取这些变量,然后将它们传递给 EVAL 脚本。由于在脚本实际启动之前不能保证脚本的原子性质,并且您需要在调用 EVAL 启动脚本之前获取这些变量,这就留下了一个空缺,这些变量的状态可能会在 GET 和传递它们之间发生变化评估。因此,对于一组非常重要的用例,您对 WATCH 的原子性保证是 EVAL 所没有的。

那么为什么要讨论弃用事务,因为这会导致重要的 Redis 功能丢失?还是实际上有一种方法可以使用我还不了解的 EVAL 脚本来执行此操作?或者是否有计划的功能可以为 EVAL 解决这个问题? (假设的例子:如果他们让 WATCH 与 EVAL 一起工作,就像 WATCH 与 EXEC 一起工作一样,那可能会奏效。)

有解决办法吗?或者我是否理解 Redis 从长远来看可能不是完全事务安全的?

最佳答案

的确,lua 脚本可以做任何事务可以做的事情,但我不认为 Redis 事务会消失。

EVAL script does not let you watch variables

当一个 eval 脚本运行时,其他任何东西都不能同时运行。所以,watching 变量是没有意义的。一旦您读取了脚本中的值,您就可以确定没有其他人修改过这些变量。

The problem I see with EVAL is that you cannot GET the state of those variables inside of the script and make a unique set of writes based on the state of those variables.

不是真的。您可以将 key 传递给 eval 脚本。在您的 eval 脚本中,您可以从 Redis 读取值,然后根据这些值有条件地执行其他命令。

脚本仍然是确定性的。如果您使用该脚本并在从属服务器上运行它,它仍将执行相同的写入命令,因为主从服务器具有相同的数据。

关于Redis:为什么 Lua 脚本要取代事务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10532520/

有关Redis:为什么 Lua 脚本要取代事务?的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  3. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  4. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  5. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  6. ruby - 难道Lua没有和Ruby的method_missing相媲美的东西吗? - 2

    我好像记得Lua有类似Ruby的method_missing的东西。还是我记错了? 最佳答案 表的metatable的__index和__newindex可以用于与Ruby的method_missing相同的效果。 关于ruby-难道Lua没有和Ruby的method_missing相媲美的东西吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/7732154/

  7. ruby - 为什么 4.1%2 使用 Ruby 返回 0.0999999999999996?但是 4.2%2==0.2 - 2

    为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返

  8. ruby - ruby 中的 TOPLEVEL_BINDING 是什么? - 2

    它不等于主线程的binding,这个toplevel作用域是什么?此作用域与主线程中的binding有何不同?>ruby-e'putsTOPLEVEL_BINDING===binding'false 最佳答案 事实是,TOPLEVEL_BINDING始终引用Binding的预定义全局实例,而Kernel#binding创建的新实例>Binding每次封装当前执行上下文。在顶层,它们都包含相同的绑定(bind),但它们不是同一个对象,您无法使用==或===测试它们的绑定(bind)相等性。putsTOPLEVEL_BINDINGput

  9. ruby-on-rails - 独立 ruby​​ 脚本的配置文件 - 2

    我有一个在Linux服务器上运行的ruby​​脚本。它不使用rails或任何东西。它基本上是一个命令行ruby​​脚本,可以像这样传递参数:./ruby_script.rbarg1arg2如何将参数抽象到配置文件(例如yaml文件或其他文件)中?您能否举例说明如何做到这一点?提前谢谢你。 最佳答案 首先,您可以运行一个写入YAML配置文件的独立脚本:require"yaml"File.write("path_to_yaml_file",[arg1,arg2].to_yaml)然后,在您的应用中阅读它:require"yaml"arg

  10. ruby - 我可以使用 aws-sdk-ruby 在 AWS S3 上使用事务性文件删除/上传吗? - 2

    我发现ActiveRecord::Base.transaction在复杂方法中非常有效。我想知道是否可以在如下事务中从AWSS3上传/删除文件:S3Object.transactiondo#writeintofiles#raiseanexceptionend引发异常后,每个操作都应在S3上回滚。S3Object这可能吗?? 最佳答案 虽然S3API具有批量删除功能,但它不支持事务,因为每个删除操作都可以独立于其他操作成功/失败。该API不提供任何批量上传功能(通过PUT或POST),因此每个上传操作都是通过一个独立的API调用完成的

随机推荐