From cea30f884089d58c63d705941b61d897817ba3ca Mon Sep 17 00:00:00 2001 From: Pieter Noordhuis Date: Mon, 18 Jun 2012 22:39:22 -0700 Subject: [PATCH] Some small grammatical changes (by @ShawnMilo) Reapplied to the reformatted tree. Fixes #119. --- commands/bgsave.md | 4 +- commands/blpop.md | 2 +- commands/config get.md | 8 +- commands/config set.md | 16 +-- commands/dbsize.md | 2 +- commands/dump.md | 2 +- commands/eval.md | 198 ++++++++++++++++++------------------- commands/script exists.md | 11 ++- commands/script load.md | 2 +- topics/data-types-intro.md | 4 +- topics/persistence.md | 2 +- 11 files changed, 125 insertions(+), 126 deletions(-) diff --git a/commands/bgsave.md b/commands/bgsave.md index 7a65e2e3b7..4db91e539b 100644 --- a/commands/bgsave.md +++ b/commands/bgsave.md @@ -1,7 +1,7 @@ Save the DB in background. The OK code is immediately returned. -Redis forks, the parent continues to server the clients, the child saves the DB -on disk then exit. +Redis forks, the parent continues to serve the clients, the child saves the DB +on disk then exits. A client my be able to check if the operation succeeded using the `LASTSAVE` command. diff --git a/commands/blpop.md b/commands/blpop.md index 24ed8f24ec..6ae9f1d926 100644 --- a/commands/blpop.md +++ b/commands/blpop.md @@ -6,7 +6,7 @@ given keys being checked in the order that they are given. ## Non-blocking behavior -When `BLPOP` is called, if at least one of the specified keys contain a +When `BLPOP` is called, if at least one of the specified keys contains a non-empty list, an element is popped from the head of the list and returned to the caller together with the `key` it was popped from. diff --git a/commands/config get.md b/commands/config get.md index c35cd8af1f..5e248879f5 100644 --- a/commands/config get.md +++ b/commands/config get.md @@ -6,7 +6,7 @@ can read the whole configuration of a server using this command. The symmetric command used to alter the configuration at run time is `CONFIG SET`. -`CONFIG GET` takes a single argument, that is glob style pattern. +`CONFIG GET` takes a single argument, which is a glob-style pattern. All the configuration parameters matching this parameter are reported as a list of key-value pairs. Example: @@ -19,7 +19,7 @@ Example: 5) "set-max-intset-entries" 6) "512" -You can obtain a list of all the supported configuration parameters typing +You can obtain a list of all the supported configuration parameters by typing `CONFIG GET *` in an open `redis-cli` prompt. All the supported parameters have the same meaning of the equivalent @@ -30,9 +30,9 @@ following important differences: * Where bytes or other quantities are specified, it is not possible to use the `redis.conf` abbreviated form (10k 2gb ... and so forth), everything - should be specified as a well formed 64 bit integer, in the base unit of the + should be specified as a well-formed 64-bit integer, in the base unit of the configuration directive. -* The save parameter is a single string of space separated integers. +* The save parameter is a single string of space-separated integers. Every pair of integers represent a seconds/modifications threshold. For instance what in `redis.conf` looks like: diff --git a/commands/config set.md b/commands/config set.md index dc845853c7..b74244e23e 100644 --- a/commands/config set.md +++ b/commands/config set.md @@ -8,8 +8,7 @@ issuing a `CONFIG GET *` command, that is the symmetrical command used to obtain information about the configuration of a running Redis instance. All the configuration parameters set using `CONFIG SET` are immediately loaded -by Redis that will start acting as specified starting from the next command -executed. +by Redis and will take effect starting with the next command executed. All the supported parameters have the same meaning of the equivalent configuration parameter used in the [redis.conf][hgcarr22rc] file, with the @@ -19,9 +18,9 @@ following important differences: * Where bytes or other quantities are specified, it is not possible to use the `redis.conf` abbreviated form (10k 2gb ... and so forth), everything - should be specified as a well formed 64 bit integer, in the base unit of the + should be specified as a well-formed 64-bit integer, in the base unit of the configuration directive. -* The save parameter is a single string of space separated integers. +* The save parameter is a single string of space-separated integers. Every pair of integers represent a seconds/modifications threshold. For instance what in `redis.conf` looks like: @@ -33,16 +32,17 @@ that means, save after 900 seconds if there is at least 1 change to the dataset, and after 300 seconds if there are at least 10 changes to the datasets, should be set using `CONFIG SET` as "900 1 300 10". -It is possible to switch persistence from RDB snapshotting to append only file +It is possible to switch persistence from RDB snapshotting to append-only file (and the other way around) using the `CONFIG SET` command. -For more information about how to do that please check [persistence page][tp]. +For more information about how to do that please check the [persistence +page][tp]. [tp]: /topics/persistence In general what you should know is that setting the `appendonly` parameter to -`yes` will start a background process to save the initial append only file +`yes` will start a background process to save the initial append-only file (obtained from the in memory data set), and will append all the subsequent -commands on the append only file, thus obtaining exactly the same effect of a +commands on the append-only file, thus obtaining exactly the same effect of a Redis server that started with AOF turned on since the start. You can have both the AOF enabled with RDB snapshotting if you want, the two diff --git a/commands/dbsize.md b/commands/dbsize.md index 8818785166..fe82aa78cb 100644 --- a/commands/dbsize.md +++ b/commands/dbsize.md @@ -1,4 +1,4 @@ -Return the number of keys in the currently selected database. +Return the number of keys in the currently-selected database. @return diff --git a/commands/dump.md b/commands/dump.md index fd92bb9bd6..c07589b481 100644 --- a/commands/dump.md +++ b/commands/dump.md @@ -6,7 +6,7 @@ command. The serialization format is opaque and non-standard, however it has a few semantical characteristics: -* It contains a 64bit checksum that is used to make sure errors will be +* It contains a 64-bit checksum that is used to make sure errors will be detected. The `RESTORE` command makes sure to check the checksum before synthesizing a key using the serialized value. diff --git a/commands/eval.md b/commands/eval.md index 602c30df6e..15df5f6cb1 100644 --- a/commands/eval.md +++ b/commands/eval.md @@ -53,9 +53,9 @@ uses should be passed using the KEYS array, in the following way: > eval "return redis.call('set',KEYS[1],'bar')" 1 foo OK -The reason for passing keys in the proper way is that, before of `EVAL` all the -Redis commands could be analyzed before execution in order to establish what are -the keys the command will operate on. +The reason for passing keys in the proper way is that, before `EVAL` all the +Redis commands could be analyzed before execution in order to establish what +keys the command will operate on. In order for this to be true for `EVAL` also keys must be explicit. This is useful in many ways, but especially in order to make sure Redis Cluster @@ -73,15 +73,15 @@ protocol using a set of conversion rules. Redis return values are converted into Lua data types when Lua calls a Redis command using call() or pcall(). -Similarly Lua data types are converted into Redis protocol when a Lua script -returns some value, so that scripts can control what `EVAL` will reply to the +Similarly Lua data types are converted into the Redis protocol when a Lua script +returns a value, so that scripts can control what `EVAL` will return to the client. This conversion between data types is designed in a way that if a Redis type is converted into a Lua type, and then the result is converted back into a Redis type, the result is the same as of the initial value. -In other words there is a one to one conversion between Lua and Redis types. +In other words there is a one-to-one conversion between Lua and Redis types. The following table shows you all the conversions rules: **Redis to Lua** conversion table. @@ -102,12 +102,12 @@ The following table shows you all the conversions rules: * Lua table with a single `err` field -> Redis error reply * Lua boolean false -> Redis Nil bulk reply. -There is an additional Lua to Redis conversion rule that has no corresponding +There is an additional Lua-to-Redis conversion rule that has no corresponding Redis to Lua conversion rule: * Lua boolean true -> Redis integer reply with value of 1. -The followings are a few conversion examples: +Here are a few conversion examples: > eval "return 10" 0 (integer) 10 @@ -121,9 +121,9 @@ The followings are a few conversion examples: > eval "return redis.call('get','foo')" 0 "bar" -The last example shows how it is possible to directly return from Lua the return -value of `redis.call()` and `redis.pcall()` with the result of returning exactly -what the called command would return if called directly. +The last example shows how it is possible to receive the exact return value of +`redis.call()` or `redis.pcall()` from Lua that would be returned if the command +was called directly. ## Atomicity of scripts @@ -141,9 +141,9 @@ is running no other client can execute commands since the server is busy. ## Error handling -As already stated calls to `redis.call()` resulting into a Redis command error -will stop the execution of the script and will return that error back, in a way -that makes it obvious that the error was generated by a script: +As already stated, calls to `redis.call()` resulting in a Redis command error +will stop the execution of the script and will return the error, in a way that +makes it obvious that the error was generated by a script: > del foo (integer) 1 @@ -154,8 +154,8 @@ that makes it obvious that the error was generated by a script: Using the `redis.pcall()` command no error is raised, but an error object is returned in the format specified above (as a Lua table with an `err` field). -The user can later return this exact error to the user just returning the error -object returned by `redis.pcall()`. +The script can pass the exact error to the user by returning the error object +returned by `redis.pcall()`. ## Bandwidth and EVALSHA @@ -164,7 +164,7 @@ Redis does not need to recompile the script every time as it uses an internal caching mechanism, however paying the cost of the additional bandwidth may not be optimal in many contexts. -On the other hand defining commands using a special command or via `redis.conf` +On the other hand, defining commands using a special command or via `redis.conf` would be a problem for a few reasons: * Different instances may have different versions of a command implementation. @@ -175,18 +175,18 @@ would be a problem for a few reasons: * Reading an application code the full semantic could not be clear since the application would call commands defined server side. -In order to avoid the above three problems and at the same time don't incur in -the bandwidth penalty, Redis implements the `EVALSHA` command. +In order to avoid these problems while avoiding the bandwidth penalty, Redis +implements the `EVALSHA` command. -`EVALSHA` works exactly as `EVAL`, but instead of having a script as first -argument it has the SHA1 sum of a script. +`EVALSHA` works exactly like `EVAL`, but instead of having a script as the first +argument it has the SHA1 digest of a script. The behavior is the following: -* If the server still remembers a script whose SHA1 sum was the one specified, - the script is executed. +* If the server still remembers a script with a matching SHA1 digest, the script + is executed. -* If the server does not remember a script with this SHA1 sum, a special error - is returned that will tell the client to use `EVAL` instead. +* If the server does not remember a script with this SHA1 digest, a special + error is returned telling the client to use `EVAL` instead. Example: @@ -200,11 +200,11 @@ Example: (error) `NOSCRIPT` No matching script. Please use `EVAL`. The client library implementation can always optimistically send `EVALSHA` under -the hoods even when the client actually called `EVAL`, in the hope the script -was already seen by the server. +the hood even when the client actually calls `EVAL`, in the hope the script was +already seen by the server. If the `NOSCRIPT` error is returned `EVAL` will be used instead. -Passing keys and arguments as `EVAL` additional arguments is also very useful in +Passing keys and arguments as additional `EVAL` arguments is also very useful in this context as the script string remains constant and can be efficiently cached by Redis. @@ -214,27 +214,26 @@ Executed scripts are guaranteed to be in the script cache **forever**. This means that if an `EVAL` is performed against a Redis instance all the subsequent `EVALSHA` calls will succeed. -The only way to flush the script cache is by explicitly calling the SCRIPT FLUSH -command, that will _completely flush_ the scripts cache removing all the scripts -executed so far. +The only way to flush the script cache is by explicitly calling the SCRIPT +FLUSH command, which will _completely flush_ the scripts cache removing all the +scripts executed so far. This is usually needed only when the instance is going to be instantiated for another customer or application in a cloud environment. The reason why scripts can be cached for long time is that it is unlikely for -a well written application to have so many different scripts to create memory +a well written application to have enough different scripts to cause memory problems. Every script is conceptually like the implementation of a new command, and even -a large application will likely have just a few hundreds of that. -Even if the application is modified many times and scripts will change, still -the memory used is negligible. +a large application will likely have just a few hundred of them. +Even if the application is modified many times and scripts will change, the +memory used is negligible. The fact that the user can count on Redis not removing scripts is semantically a very good thing. -For instance an application taking a persistent connection to Redis can stay -sure that if a script was sent once it is still in memory, thus for instance can -use EVALSHA against those scripts in a pipeline without the chance that an error -will be generated since the script is not known (we'll see this problem in its -details later). +For instance an application with a persistent connection to Redis can be sure +that if a script was sent once it is still in memory, so EVALSHA can be used +against those scripts in a pipeline without the chance of an error being +generated due to an unknown script (we'll see this problem in detail later). ## The SCRIPT command @@ -244,9 +243,9 @@ SCRIPT currently accepts three different commands: * SCRIPT FLUSH. This command is the only way to force Redis to flush the scripts cache. - It is mostly useful in a cloud environment where the same instance can be + It is most useful in a cloud environment where the same instance can be reassigned to a different user. - It is also useful for testing client libraries implementations of the + It is also useful for testing client libraries' implementations of the scripting feature. * SCRIPT EXISTS _sha1_ _sha2_... _shaN_. @@ -263,59 +262,59 @@ SCRIPT currently accepts three different commands: operation), without the need to actually execute the script. * SCRIPT KILL. - This command is the only wait to interrupt a long running script that reached + This command is the only way to interrupt a long-running script that reaches the configured maximum execution time for scripts. - The SCRIPT KILL command can only be used with scripts that did not modified - the dataset during their execution (since stopping a read only script does not - violate the scripting engine guaranteed atomicity). + The SCRIPT KILL command can only be used 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). See the next sections for more information about long running scripts. ## Scripts as pure functions A very important part of scripting is writing scripts that are pure functions. -Scripts executed in a Redis instance are replicated on slaves sending the same -script, instead of the resulting commands. +Scripts executed in a Redis instance are replicated on slaves by sending the +script -- not the resulting commands. The same happens for the Append Only File. -The reason is that scripts are much faster than sending commands one after the -other to a Redis instance, so if the client is taking the master very busy -sending scripts, turning this scripts into single commands for the slave / 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 network -is a lot more work for Redis compared to dispatching a command invoked by Lua -scripts). +The reason is that sending a script to another Redis instance is much +faster than sending the multiple commands the script generates, so if the +client is sending many scripts to the master, converting the scripts into +individual commands for the slave / 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 network is a lot more work for Redis compared +to dispatching a command invoked by Lua scripts). The only drawback with this approach is that scripts are required to have the following property: * 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) + 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. Things like using the system time, calling Redis random commands like `RANDOMKEY`, or using Lua random number generator, could result into scripts -that will not evaluate always in the same way. +that will not always evaluate in the same way. In order to enforce this behavior in scripts Redis does the following: * Lua does not export commands to access the system time or other external state. -* Redis will block the script with an error if a script will call a Redis +* 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`. - This means that if a script is read only and does not modify the data set it + This means that if a script is read-only and does not modify the data set it is free to call those commands. - Note that a _random command_ does not necessarily identifies a command that - uses random numbers: any non deterministic command is considered a random - command (the best example in this regard is the `TIME` command). + Note that a _random command_ does not necessarily mean a command that uses + random numbers: any non-deterministic command is considered a random command + (the best example in this regard is the `TIME` command). * Redis commands that may return elements in random order, like `SMEMBERS` (because Redis Sets are _unordered_) have a different behavior when called - from Lua, and undergone a silent lexicographical sorting filter before - returning data to Lua scripts. + from Lua, and undergo a silent lexicographical sorting filter before returning + data to Lua scripts. So `redis.call("smembers",KEYS[1])` will always return the Set elements in the same order, while the same command invoked from normal clients may return different results even if the key contains exactly the same elements. @@ -326,12 +325,12 @@ In order to enforce this behavior in scripts Redis does the following: This means that calling `math.random` will always generate the same sequence of numbers every time a script is executed if `math.randomseed` is not used. -However the user is still able to write commands with random behaviors using the +However the user is still able to write commands with random behavior using the following simple trick. Imagine I want to write a Redis script that will populate a list with N random integers. -I can start writing the following script, using a small Ruby program: +I can start with this small Ruby program: require 'rubygems' require 'redis' @@ -366,11 +365,11 @@ following elements: 9) "0.74990198051087" 10) "0.17082803611217" -In order to make it a pure function, but still making sure that every invocation +In order to make it a pure function, but still be sure that every invocation of the script will result in different random elements, we can simply add an -additional argument to the script, that will be used in order to seed the Lua -pseudo random number generator. -The new script will be like the following: +additional argument to the script that will be used in order to seed the Lua +pseudo-random number generator. +The new script is as follows: RandomPushScript = < eval 'a=10' 0 @@ -415,10 +414,10 @@ returns with an error: Accessing a _non existing_ global variable generates a similar error. -Using Lua debugging functionalities or other approaches like altering the meta -table used to implement global protections, in order to circumvent globals -protection, is not hard. -However it is hardly possible to do it accidentally. +Using Lua debugging functionality or other approaches like altering the meta +table used to implement global protections in order to circumvent globals +protection is not hard. +However it is difficult to do it accidentally. If the user messes with the Lua global state, the consistency of AOF and replication is not guaranteed: don't do it. @@ -440,7 +439,7 @@ The Redis Lua interpreter loads the following Lua libraries: Every Redis instance is _guaranteed_ to have all the above libraries so you can be sure that the environment for your Redis scripts is always the same. -The CJSON library allows to manipulate JSON data in a very fast way from Lua. +The CJSON library provides extremely fast JSON maniplation within Lua. All the other libraries are standard Lua libraries. ## Emitting Redis logs from scripts @@ -457,7 +456,7 @@ It is possible to write to the Redis log file from Lua scripts using the * `redis.LOG_NOTICE` * `redis.LOG_WARNING` -They exactly correspond to the normal Redis log levels. +They correspond directly to the normal Redis log levels. Only logs emitted by scripting using a log level that is equal or greater than the currently configured Redis instance log level will be emitted. @@ -472,42 +471,41 @@ Will generate the following: ## Sandbox and maximum execution time -Scripts should never try to access the external system, like the file system, -nor calling any other system call. -A script should just do its work operating on Redis data and passed arguments. +Scripts should never try to access the external system, like the file system or +any other system call. +A script should only operate on Redis data and passed arguments. Scripts are also subject to a maximum execution time (five seconds by default). -This default timeout is huge since a script should run usually in a sub -millisecond amount of time. -The limit is mostly needed in order to avoid problems when developing scripts -that may loop forever for a programming error. +This default timeout is huge since a script should usually run in under a +millisecond. +The limit is mostly to handle accidental infinite loops created during +development. It is possible to modify the maximum time a script can be executed with -milliseconds precision, either via `redis.conf` or using the CONFIG GET / CONFIG +millisecond precision, either via `redis.conf` or using the CONFIG GET / CONFIG SET command. The configuration parameter affecting max execution time is called `lua-time-limit`. When a script reaches the timeout it is not automatically terminated by Redis since this violates the contract Redis has with the scripting engine to ensure -that scripts are atomic in nature. -Stopping a script half-way means to possibly leave the dataset with half-written -data inside. +that scripts are atomic. +Interrupting a script means potentially leaving the dataset with half-written +data. For this reasons when a script executes for more than the specified time the following happens: -* Redis logs that a script that is running for too much time is still in - execution. +* Redis logs that a script is running too long. * It starts accepting commands again from other clients, but will reply with a BUSY error to all the clients sending normal commands. The only allowed commands in this status are `SCRIPT KILL` and `SHUTDOWN NOSAVE`. -* It is possible to terminate a script that executed only read-only commands +* It is possible to terminate a script that executes only read-only commands using the `SCRIPT KILL` command. - This does not violate the scripting semantic as no data was yet written on the + This does not violate the scripting semantic as no data was yet written to the dataset by the script. * If the script already called write commands the only allowed command becomes - `SHUTDOWN NOSAVE` that stops the server not saving the current data set on + `SHUTDOWN NOSAVE` that stops the server without saving the current data set on disk (basically the server is aborted). ## EVALSHA in the context of pipelining @@ -525,5 +523,5 @@ The client library implementation should take one of the following approaches: * Accumulate all the commands to send into the pipeline, then check for `EVAL` commands and use the `SCRIPT EXISTS` command to check if all the scripts are already defined. - If not add `SCRIPT LOAD` commands on top of the pipeline as required, and use + If not, add `SCRIPT LOAD` commands on top of the pipeline as required, and use `EVALSHA` for all the `EVAL` calls. diff --git a/commands/script exists.md b/commands/script exists.md index b1f7cf7e37..435b4150a0 100644 --- a/commands/script exists.md +++ b/commands/script exists.md @@ -1,7 +1,8 @@ Returns information about the existence of the scripts in the script cache. -This command accepts one or more SHA1 sums and returns a list of ones or zeros -to signal if the scripts are already defined or not inside the script cache. +This command accepts one or more SHA1 digests and returns a list of ones or +zeros to signal if the scripts are already defined or not inside the script +cache. This can be useful before a pipelining operation to ensure that scripts are loaded (and if not, to load them using `SCRIPT LOAD`) so that the pipelining operation can be performed solely using `EVALSHA` instead of `EVAL` to save @@ -13,9 +14,9 @@ Lua scripting. @return @multi-bulk-reply The command returns an array of integers that correspond to -the specified SHA1 sum arguments. -For every corresponding SHA1 sum of a script that actually exists in the script -cache, an 1 is returned, otherwise 0 is returned. +the specified SHA1 digest arguments. +For every corresponding SHA1 digest of a script that actually exists in the +script cache, an 1 is returned, otherwise 0 is returned. @example diff --git a/commands/script load.md b/commands/script load.md index 4709695bec..7adbd4e890 100644 --- a/commands/script load.md +++ b/commands/script load.md @@ -14,5 +14,5 @@ Lua scripting. @return -@bulk-reply This command returns the SHA1 sum of the script added into the +@bulk-reply This command returns the SHA1 digest of the script added into the script cache. diff --git a/topics/data-types-intro.md b/topics/data-types-intro.md index 5be69f87bb..3feb1024f2 100644 --- a/topics/data-types-intro.md +++ b/topics/data-types-intro.md @@ -293,7 +293,7 @@ Our first attempt (that is broken) can be the following. Let's suppose we want to get a unique ID for the tag "redis": * In order to make this algorithm binary safe (they are just tags but think to - utf8, spaces and so forth) we start performing the SHA1 sum of the tag. + utf8, spaces and so forth) we start performing the SHA1 digest of the tag. SHA1(redis) = b840fc02d524045429941cc15f59e41cb7be6c52. * Let's check if this tag is already associated with a unique ID with the command *GET tag:b840fc02d524045429941cc15f59e41cb7be6c52:id*. @@ -313,7 +313,7 @@ return the wrong ID to the caller. To fix the algorithm is not hard fortunately, and this is the sane version: * In order to make this algorithm binary safe (they are just tags but think to - utf8, spaces and so forth) we start performing the SHA1 sum of the tag. + utf8, spaces and so forth) we start performing the SHA1 digest of the tag. SHA1(redis) = b840fc02d524045429941cc15f59e41cb7be6c52. * Let's check if this tag is already associated with a unique ID with the command *GET tag:b840fc02d524045429941cc15f59e41cb7be6c52:id*. diff --git a/topics/persistence.md b/topics/persistence.md index 8d6df85ec5..2e4dd67b33 100644 --- a/topics/persistence.md +++ b/topics/persistence.md @@ -276,7 +276,7 @@ for best results. It is important to understand that this systems can easily fail if not coded in the right way. At least make absolutely sure that after the transfer is completed you are able to verify the file size (that should match the one of -the file you copied) and possibly the SHA1 sum if you are using a VPS. +the file you copied) and possibly the SHA1 digest if you are using a VPS. You also need some kind of independent alert system if the transfer of fresh backups is not working for some reason.