Skip to content

Commit

Permalink
The universe is 80 characters wide...
Browse files Browse the repository at this point in the history
  • Loading branch information
pietern committed Jun 18, 2012
1 parent 3e542b3 commit 066c91d
Show file tree
Hide file tree
Showing 93 changed files with 754 additions and 618 deletions.
39 changes: 39 additions & 0 deletions Rakefile
Expand Up @@ -39,3 +39,42 @@ task :spellcheck do
puts "#{file}: #{words.uniq.sort.join(" ")}" if words.any?
end
end

namespace :format do

def format(file)
return unless File.exist?(file)

STDOUT.print "formatting #{file}..."
STDOUT.flush

matcher = /^(?:\A|\r?\n)((?:[a-zA-Z].+?\r?\n)+)/m
body = File.read(file).gsub(matcher) do |match|
formatted = nil

IO.popen("par p0s0w80", "r+") do |io|
io.puts match
io.close_write
formatted = io.read
end

formatted
end

File.open(file, "w") do |f|
f.print body
end

STDOUT.puts
end

task :file, :path do |t, args|
format(args[:path])
end

task :all do
Dir["commands/*.md"].each do |path|
format(path)
end
end
end
26 changes: 16 additions & 10 deletions commands/append.md
@@ -1,6 +1,6 @@
If `key` already exists and is a string, this command appends the `value` at
the end of the string. If `key` does not exist it is created and set as an
empty string, so `APPEND` will be similar to `SET` in this special case.
If `key` already exists and is a string, this command appends the `value` at the
end of the string. If `key` does not exist it is created and set as an empty
string, so `APPEND` will be similar to `SET` in this special case.

@return

Expand All @@ -16,9 +16,9 @@ empty string, so `APPEND` will be similar to `SET` in this special case.

## Pattern: Time series

the `APPEND` command can be used to create a very compact representation of
a list of fixed-size samples, usually referred as *time series*.
Every time a new sample arrives we can store it using the command
the `APPEND` command can be used to create a very compact representation of a
list of fixed-size samples, usually referred as *time series*. Every time a new
sample arrives we can store it using the command

APPEND timeseries "fixed-size sample"

Expand All @@ -28,12 +28,18 @@ Accessing individual elements in the time series is not hard:
* `GETRANGE` allows for random access of elements. If our time series have an associated time information we can easily implement a binary search to get range combining `GETRANGE` with the Lua scripting engine available in Redis 2.6.
* `SETRANGE` can be used to overwrite an existing time serie.

The limitations of this pattern is that we are forced into an append-only mode of operation, there is no way to cut the time series to a given size easily because Redis currently lacks a command able to trim string objects. However the space efficiency of time series stored in this way is remarkable.
The limitations of this pattern is that we are forced into an append-only mode
of operation, there is no way to cut the time series to a given size easily
because Redis currently lacks a command able to trim string objects. However the
space efficiency of time series stored in this way is remarkable.

Hint: it is possible to switch to a different key based on the current Unix time, in this way it is possible to have just a relatively small amount of samples per key, to avoid dealing with very big keys, and to make this pattern more
friendly to be distributed across many Redis instances.
Hint: it is possible to switch to a different key based on the current Unix
time, in this way it is possible to have just a relatively small amount of
samples per key, to avoid dealing with very big keys, and to make this pattern
more friendly to be distributed across many Redis instances.

An example sampling the temperature of a sensor using fixed-size strings (using a binary format is better in real implementations).
An example sampling the temperature of a sensor using fixed-size strings (using
a binary format is better in real implementations).

@cli
APPEND ts "0043"
Expand Down
13 changes: 6 additions & 7 deletions commands/auth.md
@@ -1,11 +1,10 @@
Request for authentication in a password protected Redis server.
Redis can be instructed to require a password before allowing clients
to execute commands. This is done using the `requirepass` directive in the
configuration file.
Request for authentication in a password protected Redis server. Redis can be
instructed to require a password before allowing clients to execute commands.
This is done using the `requirepass` directive in the configuration file.

If `password` matches the password in the configuration file, the server replies with
the `OK` status code and starts accepting commands.
Otherwise, an error is returned and the clients needs to try a new password.
If `password` matches the password in the configuration file, the server replies
with the `OK` status code and starts accepting commands. Otherwise, an error is
returned and the clients needs to try a new password.

**Note**: because of the high performance nature of Redis, it is possible to try
a lot of passwords in parallel in very short time, so make sure to generate
Expand Down
12 changes: 8 additions & 4 deletions commands/bgrewriteaof.md
@@ -1,17 +1,21 @@
Instruct Redis to start an [Append Only File][aof] rewrite process. The rewrite will create a small optimized version of the current Append Only File.
Instruct Redis to start an [Append Only File][aof] rewrite process. The rewrite
will create a small optimized version of the current Append Only File.

[aof]: /topics/persistence#append-only-file

If `BGREWRITEAOF` fails, no data gets lost as the old AOF will be untouched.

The rewrite will be only triggered by Redis if there is not already a background process doing persistence. Specifically:
The rewrite will be only triggered by Redis if there is not already a background
process doing persistence. Specifically:

* If a Redis child is creating a snapshot on disk, the AOF rewrite is *scheduled* but not started until the saving child producing the RDB file terminates. In this case the `BGREWRITEAOF` will still return an OK code, but with an appropriate message. You can check if an AOF rewrite is scheduled looking at the `INFO` command starting from Redis 2.6.
* If an AOF rewrite is already in progress the command returns an error and no AOF rewrite will be scheduled for a later time.

Since Redis 2.4 the AOF rewrite is automatically triggered by Redis, however the `BGREWRITEAOF` command can be used to trigger a rewrite at any time.
Since Redis 2.4 the AOF rewrite is automatically triggered by Redis, however the
`BGREWRITEAOF` command can be used to trigger a rewrite at any time.

Please refer to the [persistence documentation][persistence] for detailed information.
Please refer to the [persistence documentation][persistence] for detailed
information.

[persistence]: /topics/persistence

Expand Down
11 changes: 6 additions & 5 deletions commands/bgsave.md
@@ -1,11 +1,12 @@


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. A client my be able to check if the
operation succeeded using the `LASTSAVE` command.
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. A client my be able to check if the operation succeeded using the
`LASTSAVE` command.

Please refer to the [persistence documentation][persistence] for detailed information.
Please refer to the [persistence documentation][persistence] for detailed
information.

[persistence]: /topics/persistence

Expand Down
41 changes: 20 additions & 21 deletions commands/bitcount.md
Expand Up @@ -4,12 +4,11 @@ By default all the bytes contained in the string are examined. It is possible
to specify the counting operation only in an interval passing the additional
arguments *start* and *end*.

Like for the `GETRANGE` command start and end can contain negative values
in order to index bytes starting from the end of the string, where -1 is the
last byte, -2 is the penultimate, and so forth.
Like for the `GETRANGE` command start and end can contain negative values in
order to index bytes starting from the end of the string, where -1 is the last
byte, -2 is the penultimate, and so forth.

Non existing keys are treated as empty strings, so the command will return
zero.
Non existing keys are treated as empty strings, so the command will return zero.

@return

Expand All @@ -28,32 +27,32 @@ The number of bits set to 1.
## Pattern: real time metrics using bitmaps

Bitmaps are a very space efficient representation of certain kinds of
information. One example is a web application that needs the history
of user visits, so that for instance it is possible to determine what
users are good targets of beta features, or for any other purpose.
information. One example is a web application that needs the history of user
visits, so that for instance it is possible to determine what users are good
targets of beta features, or for any other purpose.

Using the `SETBIT` command this is trivial to accomplish, identifying every
day with a small progressive integer. For instance day 0 is the first day
the application was put online, day 1 the next day, and so forth.
day with a small progressive integer. For instance day 0 is the first day the
application was put online, day 1 the next day, and so forth.

Every time an user performs a page view, the application can register that
in the current day the user visited the web site using the `SETBIT` command
setting the bit corresponding to the current day.
Every time an user performs a page view, the application can register that in
the current day the user visited the web site using the `SETBIT` command setting
the bit corresponding to the current day.

Later it will be trivial to know the number of single days the user visited
the web site simply calling the `BITCOUNT` command against the bitmap.
Later it will be trivial to know the number of single days the user visited the
web site simply calling the `BITCOUNT` command against the bitmap.

A similar pattern where user IDs are used instead of days is described
in the article called "[Fast easy realtime metrics using Redis bitmaps][bitmaps]".
A similar pattern where user IDs are used instead of days is described in the
article called "[Fast easy realtime metrics using Redis bitmaps][bitmaps]".

[bitmaps]: http://blog.getspool.com/2011/11/29/fast-easy-realtime-metrics-using-redis-bitmaps

## Performance considerations

In the above example of counting days, even after 10 years the application
is online we still have just `365*10` bits of data per user, that is
just 456 bytes per user. With this amount of data `BITCOUNT` is still as fast
as any other O(1) Redis command like `GET` or `INCR`.
In the above example of counting days, even after 10 years the application is
online we still have just `365*10` bits of data per user, that is just 456 bytes
per user. With this amount of data `BITCOUNT` is still as fast as any other O(1)
Redis command like `GET` or `INCR`.

When the bitmap is big, there are two alternatives:

Expand Down
25 changes: 14 additions & 11 deletions commands/bitop.md
@@ -1,7 +1,8 @@
Perform a bitwise operation between multiple keys (containing string
values) and store the result in the destination key.
Perform a bitwise operation between multiple keys (containing string values) and
store the result in the destination key.

The `BITOP` command supports four bitwise operations: **AND**, **OR**, **XOR** and **NOT**, thus the valid forms to call the command are:
The `BITOP` command supports four bitwise operations: **AND**, **OR**, **XOR**
and **NOT**, thus the valid forms to call the command are:

+ BITOP AND *destkey srckey1 srckey2 srckey3 ... srckeyN*
+ BITOP OR *destkey srckey1 srckey2 srckey3 ... srckeyN*
Expand All @@ -15,9 +16,9 @@ The result of the operation is always stored at *destkey*.

## Handling of strings with different lengths

When an operation is performed between strings having different lengths, all
the strings shorter than the longest string in the set are treated as if
they were zero-padded up to the length of the longest string.
When an operation is performed between strings having different lengths, all the
strings shorter than the longest string in the set are treated as if they were
zero-padded up to the length of the longest string.

The same holds true for non-existing keys, that are considered as a stream of
zero bytes up to the length of the longest string.
Expand All @@ -26,7 +27,8 @@ zero bytes up to the length of the longest string.

@integer-reply

The size of the string stored into the destination key, that is equal to the size of the longest input string.
The size of the string stored into the destination key, that is equal to the
size of the longest input string.

@examples

Expand All @@ -41,7 +43,8 @@ The size of the string stored into the destination key, that is equal to the siz
`BITOP` is a good complement to the pattern documented in the `BITCOUNT` command documentation. Different bitmaps can be combined in order to obtain a target
bitmap where to perform the population counting operation.

See the article called "[Fast easy realtime metrics using Redis bitmaps][bitmaps]" for an interesting use cases.
See the article called "[Fast easy realtime metrics using Redis
bitmaps][bitmaps]" for an interesting use cases.

[bitmaps]: http://blog.getspool.com/2011/11/29/fast-easy-realtime-metrics-using-redis-bitmaps

Expand All @@ -50,6 +53,6 @@ See the article called "[Fast easy realtime metrics using Redis bitmaps][bitmaps
`BITOP` is a potentially slow command as it runs in O(N) time.
Care should be taken when running it against long input strings.

For real time metrics and statistics involving large inputs a good approach
is to use a slave (with read-only option disabled) where to perform the
bit-wise operations without blocking the master instance.
For real time metrics and statistics involving large inputs a good approach is
to use a slave (with read-only option disabled) where to perform the bit-wise
operations without blocking the master instance.
30 changes: 14 additions & 16 deletions commands/blpop.md
Expand Up @@ -21,15 +21,14 @@ that order).

## Blocking behavior

If none of the specified keys exist, `BLPOP` blocks
the connection until another client performs an `LPUSH` or `RPUSH` operation
against one of the keys.
If none of the specified keys exist, `BLPOP` blocks the connection until another
client performs an `LPUSH` or `RPUSH` operation against one of the keys.

Once new data is present on one of the lists, the client returns with the name
of the key unblocking it and the popped value.

When `BLPOP` causes a client to block and a non-zero timeout is specified, the
client will unblock returning a `nil` multi-bulk value when the specified
When `BLPOP` causes a client to block and a non-zero timeout is specified,
the client will unblock returning a `nil` multi-bulk value when the specified
timeout has expired without a push operation against at least one of the
specified keys.

Expand All @@ -38,9 +37,9 @@ be used to block indefinitely.

## Multiple clients blocking for the same keys

Multiple clients can block for the same key. They are put into
a queue, so the first to be served will be the one that started to wait
earlier, in a first-`!BLPOP` first-served fashion.
Multiple clients can block for the same key. They are put into a queue, so
the first to be served will be the one that started to wait earlier, in a
first-`!BLPOP` first-served fashion.

## `!BLPOP` inside a `!MULTI`/`!EXEC` transaction

Expand All @@ -51,8 +50,8 @@ execute the block atomically, which in turn does not allow other clients to
perform a push operation.

The behavior of `BLPOP` inside `MULTI`/`EXEC` when the list is empty is to
return a `nil` multi-bulk reply, which is the same thing that happens when the
timeout is reached. If you like science fiction, think of time flowing at
return a `nil` multi-bulk reply, which is the same thing that happens when
the timeout is reached. If you like science fiction, think of time flowing at
infinite speed inside a `MULTI`/`EXEC` block.

@return
Expand All @@ -76,12 +75,11 @@ infinite speed inside a `MULTI`/`EXEC` block.
## Pattern: Event notification

Using blocking list operations it is possible to mount different blocking
primitives. For instance for some application you may need to block
waiting for elements into a Redis Set, so that as far as a new element is
added to the Set, it is possible to retrieve it without resort to polling.
This would require a blocking version of `SPOP` that is
not available, but using blocking list operations we can easily accomplish
this task.
primitives. For instance for some application you may need to block waiting for
elements into a Redis Set, so that as far as a new element is added to the Set,
it is possible to retrieve it without resort to polling. This would require
a blocking version of `SPOP` that is not available, but using blocking list
operations we can easily accomplish this task.

The consumer will do:

Expand Down
15 changes: 8 additions & 7 deletions commands/config get.md
@@ -1,7 +1,7 @@
The `CONFIG GET` command is used to read the configuration parameters of a
running Redis server. Not all the configuration parameters are
supported in Redis 2.4, while Redis 2.6 can read the whole configuration of
a server using this command.
running Redis server. Not all the configuration parameters are supported in
Redis 2.4, while Redis 2.6 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`.
Expand All @@ -22,7 +22,8 @@ You can obtain a list of all the supported configuration parameters typing
`CONFIG GET *` in an open `redis-cli` prompt.

All the supported parameters have the same meaning of the equivalent
configuration parameter used in the [redis.conf][conf] file, with the following important differences:
configuration parameter used in the [redis.conf][conf] file, with the following
important differences:

[conf]: http://github.com/antirez/redis/raw/2.2/redis.conf

Expand All @@ -34,9 +35,9 @@ For instance what in `redis.conf` looks like:
save 900 1
save 300 10

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, will be reported by `CONFIG GET` as "900 1 300 10".
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, will be
reported by `CONFIG GET` as "900 1 300 10".

@return

Expand Down

0 comments on commit 066c91d

Please sign in to comment.