Redis means two things:
Redis is an open source, advanced key-value store. It is often referred to as a data structure server since keys can contain strings(加不加引号都被解析为字符串,但后面的集合类型都要用引号扩括起来), hashes, lists, sets and sorted sets.
Download, extract and compile Redis with:
$ wget http://redis.googlecode.com/files/redis-2.4.2.tar.gz
$ tar xzf redis-2.4.2.tar.gz
$ cd redis-2.4.2
$ make
The binaries that are now compiled are available in the src
directory. Run Redis with:
$ src/redis-server
You can interact with Redis using the built-in client:
$ src/redis-cli
redis> set foo bar
OK
redis> get foo
"bar"
Are you new to Redis? Try our online, interactive tutorial.
The Redis core team is already hacking on Redis Cluster. We already have have some kind of experimental version in the unstable branch, while a Release Candidate or at least a fully working beta is expected for the end of 2011.
可以永久存储
Other common operations provided by key-value stores are DEL to delete a given key and associated value, SET-if-not-exists (called SETNX on Redis) that sets a key only if it does not already exist, and INCR to atomically increment a number stored at a given key:
SET connections 10 INCR connections incr 为原子操作 INCR connections DEL connections INCR connections 不存在的key ,默认创建value为0,并增加1
SET resource:lock "Redis Demo"
EXPIRE resource:lock 120
This causes the key resource:lock to be deleted in 120 seconds. You can test how long a key will exist for with the TTL command. It returns the number of seconds until it will be deleted.
TTL resource:lock => 113
TTL count => -1
The -1 for the TTL of the key count means that it will never expire. Note that if you SET a key, its TTL will reset.
SET resource:lock "Redis Demo 1"
EXPIRE resource:lock 120
TTL resource:lock => 119
SET resource:lock "Redis Demo 2"
TTL resource:lock => -1 //以前监视的key已不存在
Redis also supports several more complex data structures. The first one we'll look at is a list. A list is a series of ordered values. Some of the important commands for interacting with lists are RPUSH, LPUSH, LLEN, LRANGE, LPOP, and RPOP. You can immediately begin working with a key as a list, as long as it doesn't already exist as a different type.
RPUSH puts the new value at the end of the list.
RPUSH friends "Tom" //R is short for right
RPUSH friends "Bob"
LPUSH puts the new value at the start of the list.//L is short for left
LPUSH friends "Sam"
LRANGE gives a subset of the list. It takes the index of the first element you want to retrieve as its first parameter and the index of the last element you want to retrieve as its second parameter. A value of -1 for the second parameter means to retrieve all elements in the list.
LRANGE friends 0 -1 => ["Sam","Tom","Bob"] 第一个参数为起点,第二个参数为终点,-1表示到结尾 -1 is the last element, -2 is the penultimate element of the list, and so forth.
LRANGE friends 0 1 => ["Sam","Tom"]
LRANGE friends 1 2 => ["Tom","Bob"]
Pushing IDs instead of the actual data in Redis lists(通过引用来指明对象,减少空间浪费)LLEN returns the current length of the list.
LLEN friends => 3
LPOP removes the first element from the list and returns it.
LPOP friends => "Sam"
RPOP removes the last element from the list and returns it.
RPOP friends => "Bob"
The next data structure that we'll look at is a set. A set is similar to a list, except it does not have a specific order and each element may only appear once. Some of the important commands in working with sets are SADD, SREM, SISMEMBER, SMEMBERS and SUNION.
SADD adds the given value to the set.
SADD superpowers "flight" SADD superpowers "x-ray vision" SADD superpowers "reflexes"SREM removes the given value from the set.
SREM superpowers "reflexes"
SISMEMBER tests if the given value is in the set.
SISMEMBER superpowers "flight" => true SISMEMBER superpowers "reflexes" => falseSMEMBERS returns a list of all the members of this set.
SMEMBERS superpowers => ["flight","x-ray vision"]SUNION combines two or more sets and returns the list of all elements.
SADD birdpowers "pecking" SADD birdpowers "flight" SUNION superpowers birdpowers => ["flight","x-ray vision","pecking"]The last data structure which Redis supports is the sorted set. It is similar to a regular set, but now each value has an associated score. This score is used to sort the elements in the set.
ZADD hackers 1940 "Alan Kay" ZADD hackers 1953 "Richard Stallman" ZADD hackers 1965 "Yukihiro Matsumoto" ZADD hackers 1916 "Claude Shannon" ZADD hackers 1969 "Linus Torvalds" ZADD hackers 1912 "Alan Turing"In these examples, the scores are years of birth and the values are the names of famous hackers.
ZRANGE hackers 2 4 => ["Alan Kay","Richard Stallman","Yukihiro Matsumoto"]
Redis keys
Redis keys are binary safe, this means that you can use any binary sequence as a key, from a string like "foo" to the content of a JPEG file. The empty string is also a valid key.
A few other rules about keys:
- Too long keys are not a good idea, for instance a key of 1024 bytes is not a good idea not only memory-wise, but also because the lookup of the key in the dataset may require several costly key-comparisons.
- Too short keys are often not a good idea. There is little point in writing "u:1000:pwd" as key if you can write instead "user:1000:password", the latter is more readable and the added space is little compared to the space used by the key object itself and the value object. 但是短key确实可以减少空间。
- Try to stick with a schema. For instance "object-type:id:field" can be a nice idea, like in "user:1000:password". I like to use dots for multi-words fields, like in "comment:1234:reply.to".冒号和点并没有特殊意义,这是可读性和可解析性强。
The string type
This is the simplest Redis type. If you use only this type, Redis will be something like a memcached server with persistence.
Let's play a bit with the string type:
$ redis-cli set mykey "my binary safe value" OK $ redis-cli get mykey my binary safe value
As you can see using the SET command and the GET command is trivial to set values to strings and have this strings returned back.
Values can be strings (including binary data) of every kind, for instance you can store a jpeg image inside a key.(什么意思)A value can't be bigger than 1 Gigabyte.
Even if strings are the basic values of Redis, there are interesting operations you can perform against them. For instance one is atomic increment:
$ redis-cli set counter 100 (不加引号,也被处理成字符串) OK $ redis-cli incr counter (integer) 101 $ redis-cli incr counter (integer) 102 $ redis-cli incrby counter 10 (integer) 112
The INCR command parses the string value as an integer, increments it by one, and finally sets the obtained value as the new string value. There are other similar commands like INCRBY, DECR and DECRBY.(均为原子操作) Actually internally it's always the same command, acting in a slightly different way.
Another interesting operation on string is the GETSET command, that does just what its name suggests: Set a key to a new value, returning the old value, as result. Why this is useful? Example: you have a system that increments a Redis key using the INCR command every time your web site receives a new visit. You want to collect this information one time every hour, without losing a single key. You can GETSET the key assigning it the new value of "0" and reading the old value back.//也是原子操作。
The List type
From a very general point of view a List is just a sequence of ordered elements: 10,20,1,2,3 is a list.(可以是连接也可以是数组)
Redis lists are implemented via Linked Lists.
What's the downside? (按索引查询慢)
$ redis-cli incr next.news.id (integer) 1 $ redis-cli set news:1:title "Redis is simple" OK $ redis-cli set news:1:url "http://code.google.com/p/redis" OK $ redis-cli lpush submitted.news 1 OK
We obtained an unique incremental ID for our news object just incrementing a key, then used this ID to create the object setting a key for every field in the object. Finally the ID of the new object was pushed on the submitted.news list.
SINTER that performs the intersection (取集合的交集) between different sets. So in order to reach our goal we can just use:
Operating on ranges (范围操作)Sorted sets
For sorted sets it's a joke to return these hackers sorted by their birth year because actually they are already sorted. Sorted sets are implemented via a dual-ported data structure containing both a skip list and an hash table, so every time we add an element Redis performs an O(log(N))operation.
$ redis-cli zrange hackers 0 -1 1. Alan Turing 2. Claude Shannon 3. Alan Kay 4. Richard Stallman 5. Yukihiro Matsumoto 6. Linus Torvalds
Anyway I want to order these elements the other way around, using ZREVRANGE (倒排)instead of ZRANGE this time.
可以使用多种排序方法:用SORT,或同时建另一个SSet
Sorted sets are more powerful than this. They can operate on ranges. For instance let's try to get all the individuals that were born up to the 1950. We use the ZRANGEBYSCORE command to do it: (这个命令名字起的不好)
$ redis-cli zrangebyscore hackers -inf 1950 (负无穷到1950) 1. Alan Turing 2. Claude Shannon 3. Alan Kay
$ redis-cli zremrangebyscore hackers 1940 1960 (integer) 2
Data types
Strings
You can do a number of interesting things using strings in Redis, for instance yo can:
- Use Strings as atomic counters using commands in the INCR family: INCR, DECR, INCRBY.
- Append to strings with the APPEND command.
Lists
Redis Lists are simply lists of strings, sorted by insertion order. It is possible to add elements to a Redis List pushing new elements on the head (on the left) or on the tail (on the right) of the list.
The LPUSH command inserts a new element on head, while RPUSH inserts a new element on tail. A new list is created when one of this operations is performed against an empty key. Similarly the key is removed from the key space if a list operation will empty the list. This is a very handy semantics since all the list commands will behave exactly like if called with an empty list if they are called with a non existing key as argument.
Some example of list operations and resulting lists:
LPUSH mylist a # now the list is "a" LPUSH mylist b # now the list is "b","a" RPUSH mylist c # now the list is "b","a","c" (RPUSH was used this time)
The max length of a list is 232-1 elements (4294967295, more than 4 billion of elements per list).
The main features of Redis Lists from the point of view of time complexity is the support for constant time insertion and deletion of elements near the head and tail, even with many millions of inserted items. Accessing elements is very fast near the extremes of the list but is slow if you try accessing the middle of a very big list, as it is an O(N) operation.
You can do many interesting things with Redis Lists, for instance you can:
- Model a timeline in a social network, using LPUSH in order to add new elements in the user time line, and using LRANGE in order to retrieve a few of recently inserted items.
- You can use LPUSH together with LTRIM to create a list that never exceeds a given number of elements, but just remembers the latest N elements.
- Lists can be used as a message passing primitive, See for instance the well known Resque Ruby library for creating background jobs.
- You can do a lot more with lists, this data type supports a number of commands, including blocking commands like BLPOP. Please check all the available commands operating on lists for more information.
Sets
Redis Sets are an unordered collection of Strings. It is possible to add, remove, and test for existence of members in O(1) (constant time regardless of the number of elements contained inside the Set).
集合操作非常快。
The max number of members in a set is 232-1 (4294967295, more than 4 billion of members per set).
Hashes
Redis Hashes are maps between string fields and string values, so they are the perfect data type to represent objects (eg: A User with a number of fields like name, surname, age, and so forth):
redis> HMSET user:1000 username antirez password P1pp0 age 34OK (HMSET key-value一起添加)redis> HGETALL user:10001) "username" 2) "antirez" 3) "password" 4) "P1pp0" 5) "age" 6) "34"redis> HSET user:1000 password 12345(单key-value添加)redis> HGETALL user:10001) "username" 2) "antirez" 3) "password" 4) "12345" 5) "age" 6) "34"redis>Every hash can store up to 232-1 field-value pairs (more than 4 billion).