Article main directory
Redis data types
Unlike Memcached, which only supports data records with a simple key-value structure, Redis supports much more data types. There are five commonly used data types: String, List, Hash, Set, and Sorted Set.
Redis data type memory structure analysis
Redis internally uses a redisObject object to represent all keys and values. The main information of redisObject includes data type (type), encoding method (encoding), data pointer (ptr), virtual memory (vm), etc. Type represents the specific data type of a value object, and encoding is the internal formula of different data types in redis.
RedisObject object diagram
The usage of the five data types is described below.
String type
Strings are the most basic type of Redis value. The string used in Redis is an abstract data structure based on the simple dynamic string (SDS) implemented by the C language character array by wrapping it. Its source code is defined as follows:
struct sdshdr {
int len; //len represents the length of the string stored in buf.
int free; //free represents the length of free space in buf.
char buf[]; //buf is used to store string content.
};
C language string memory structure diagram 1
Assuming that the above picture is the memory structure of the "hello" string, at this time len=5, free=2, then the length of the redis package (sds) is:
sizeof(struct sdshdr) + len + free + 1
where the size of buf is:
len + free + 1
1 means that 1 byte is used to store the terminator '\0'. Redis strings are binary safe, because binary data usually has a byte in the middle that stores '\0', which means that a Redis string can contain any kind of data, such as a JPEG image or a sequence A Ruby object to be converted. Whether binary is safe or not, a simple understanding is whether there can be '\0' in the middle of the string, as shown below:
C language string memory structure diagram 2
For the above picture, sds thinks this string is "hello world", and the character processing function of C language thinks this string is "hello".
Application scenarios
String is the most commonly used data type, and ordinary key/value storage can be classified into this category.
Common commands
(1) set - set the value corresponding to the key to a value of type String
(2) get - get the value corresponding to the key
192.168.2.129:6379> setnx name lisi
(integer) 0
192.168.2.129:6379> setnx name1 wangwu
(integer) 1
192.168.2.129:6379> get name
"zhangsan"
192.168.2.129:6379> get name1
"wangwu"
192.168.2.129:6379>
(3) mget - get the values of multiple keys in batches, and return nil if they do not exist
192.168.2.129:6379> mget name name1
1) "zhangsan"
2) "wangwu"
192.168.2.129:6379> mget name name1 name2
1) "zhangsan"
2) "wangwu"
3) (nil)
192.168.2.129:6379>
(4) incr && incrby - incr adds the value corresponding to the key and returns the new value; incrby adds the specified value
192.168.2.129:6379> get age
"20"
192.168.2.129:6379> incr age
(integer) 21
192.168.2.129:6379> set age1 "20"
OK
192.168.2.129:6379> get age1
"20"
192.168.2.129:6379> incr age1
(integer) 21
192.168.2.129:6379> incrby age 3
(integer) 24
As can be seen from the above results, when we can perform incr operations on both int-type age and string-type age1,
In fact, type=string means that the value stored is a common string, then the corresponding encoding can be raw or int. If it is int, it means that the actual redis internal storage and representation of the string is based on the numerical type, of course, the premise is The string itself can be represented by a numerical value. For example, a string such as "20" will be converted into a numerical value for calculation when incr, decr and other operations are encountered. At this time, the encoding field of redisObject is int. An error will be reported if you try to incr the name.
192.168.2.129:6379> incr name
(error) ERR value is not an integer or out of range
(5) decr && decrby - decr subtracts the value corresponding to the key and returns the new value; decrby subtracts the specified value
192.168.2.129:6379> decr age
(integer) 23
192.168.2.129:6379> decrby age 3
(integer) 20
192.168.2.129:6379>
(6) Other orders
Order |
illustrate |
setnx |
Set the value corresponding to the key to a value of type String, and return 0 if the key already exists |
setex |
Set the value corresponding to the key to a value of type String, and set the validity period |
set range |
Set the substring corresponding to the value of the key |
getrange |
Get the substring of the value corresponding to the key |
mset |
Set the values of multiple keys in batches. If successful, all values are set. Otherwise, return 0 to indicate that no values are set. |
msetnx |
Same as mset, set if it does not exist, will not overwrite the existing key |
getset |
Set the value of key and return the old value of key |
append |
Append a string to the value of the specified key and return the length of the new string |
strlen |
Get the length of the value of the specified key |
Hash type
Hash is a mapping table between fields and values of String type, that is, the actual internal storage structure of the value corresponding to the key (hash table name) of the Hash data type of redis is a HashMap, so Hash is especially suitable for storing objects. Compared to storing each property of an object as a String type, storing the entire object in a Hash type consumes less memory.
Hash data type internal structure diagram
There are currently two ways to implement HashMap: when the number of HashMap members is relatively small, Redis will use a one-dimensional array-like method for compact storage in order to save memory, instead of using the real HashMap structure. At this time, the encoding of the redisObject of the corresponding value is zipmap, when the number of members increases, it will be automatically converted into a real HashMap, and the encoding is ht at this time.
Application scenarios
Use an object to store user information, product information, order information, etc.
Common commands
(1) hset - set the value of the field in the HashMap corresponding to the key
(2) hget - get the value of the field in the HashMap corresponding to the key
192.168.2.129:6379> hset myhash name zhangsan
(integer) 1
192.168.2.129:6379> hset myhash age 20
(integer) 1
192.168.2.129:6379> hget myhash name
"zhangsan"
192.168.2.129:6379> hget myhash age
"20"
192.168.2.129:6379>
(3) hgetall - get the value of all fields in the HashMap corresponding to the key
192.168.2.129:6379> hgetall myhash
1) "name"
2) "zhangsan"
3) "age"
4) "20"
192.168.2.129:6379>
(4) Other commands
Order |
illustrate |
hsetnx |
Set the value of the field in the HashMap corresponding to the key, if it does not exist, create it first |
hmset |
Batch set the value of the field in the HashMap corresponding to the key |
hmget |
Get the value of the field in the HashMap corresponding to the key in batches |
hincrby |
Add the specified value to the value of the field in the HashMap corresponding to the key |
hexits |
Test whether the field in the HashMap corresponding to the key exists |
hlen |
Returns the number of fields in the HashMap corresponding to the key |
del |
Delete the field in the HashMap corresponding to the key |
hkeys |
Returns all fields in the HashMap corresponding to the key |
whale |
Returns the value of all fields in the HashMap corresponding to the key |
List type
The List type of Redis is actually a doubly linked list in which each element is a String type. We can add or remove elements from the head and tail of the linked list. Such a List can be used both as a stack and as a queue.
Internal diagram of List data structure
Application scenarios
Such as friend list, fan list, message queue, latest news ranking, etc.
Common commands
(1) lpush - add an element to the head of the list corresponding to the key.
(2) lrange - get the elements of the specified subscript range of the list corresponding to the key, -1 means get all elements.
(3) lpop - deletes an element from the end of the list corresponding to the key and returns the element.
192.168.2.129:6379> lpush newlist news1 news2 news3
(integer) 3
192.168.2.129:6379> lrange newlist 0 -1
1) "news3"
2) "news2"
3) "news1"
192.168.2.129:6379> lpop newlist
"news3"
192.168.2.129:6379> lrange newlist 0 -1
1) "news2"
2) "news1"
192.168.2.129:6379>
As can be seen from the above operations, lpush and lpop operate from the header.
(4) rpush - add an element to the end of the list corresponding to the key.
(5) rpop - delete an element from the end of the list corresponding to the key and return the element.
192.168.2.129:6379> rpush newlist2 news1 news2 news3
(integer) 3
192.168.2.129:6379> lrange newlist2 0 -1
1) "news1"
2) "news2"
3) "news3"
192.168.2.129:6379> rpop newlist2
"news3"
192.168.2.129:6379>
As can be seen from the above operations, rpush and rpop operate from the end of the table.
(6) Other orders
Order |
illustrate |
lensed |
Insert an element before or after a specific element of the list corresponding to the key |
lset |
Set the value of the specified subscript element in the list corresponding to the key |
lrem |
Delete n elements that are the same as value from the list corresponding to key |
ltrim |
Retains the specified range of elements in the list corresponding to the key |
rpoplpush |
Remove an element from the end of the first list and add it to the head of the second list |
llen |
Returns the length of the list corresponding to the key |
lindex |
Returns the element of index in the list corresponding to the key |
Set type
Redis collection (Set type) is an unordered collection of String type data, similar to a list of List. Unlike List, Set cannot have duplicate data. In fact, the interior of Set is implemented with HashMap, and Set only uses the key column of HashMap to store objects. Let's take a look at the source code of HashSet in java:
public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable
{
static final long serialVersionUID = -5024744406713321676L;
private transient HashMap<E,Object> map;
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
/**
* Constructs a new, empty set; the backing <tt>HashMap</tt> instance has
* default initial capacity (16) and load factor (0.75).
*/
public HashSet() {
map = new HashMap<>();
}
......
/**
* Returns an iterator over the elements in this set. The elements
* are returned in no particular order.
*
* @return an Iterator over the elements in this set
* @see ConcurrentModificationException
*/
public Iterator<E> iterator() {
return map.keySet().iterator();
}
可见创建一个HashSet的时候实际上创建了一个HashMap;Set中的元素,只是存放在了底层HashMap的key上,底层HashMap的value列为空,遍历HashSet的时候从HashMap中取出keySet来遍历。
Set底层结构示意图
应用场景
集合有取交集、并集、差集等操作,因此可以求共同好友、共同兴趣、分类标签等。
常用命令
(1)sadd——在key对应的set中添加一个元素。
(2)smembers——获取key对应的set的所有元素。
(3)spop——随机返回并删除key对应的set中的一个元素。
192.168.2.129:6379> sadd myset news1 news2 news3
(integer) 3
192.168.2.129:6379> smembers myset
1) "news3"
2) "news2"
3) "news1"
192.168.2.129:6379> spop myset
"news3"
192.168.2.129:6379>
(4)sdiff——求给定key对应的set与第一个key对应的set的差集
192.168.2.129:6379> smembers myset
1) "news3"
2) "news2"
3) "news1"
192.168.2.129:6379> sadd myset2 news3 news4 news5
(integer) 3
192.168.2.129:6379> smembers myset2
1) "news4"
2) "news3"
3) "news5"
192.168.2.129:6379> sdiff myset myset2
1) "news1"
2) "news2"
192.168.2.129:6379>
(5)suion——求给定key对应的set并集
192.168.2.129:6379> sunion myset myset2
1) "news3"
2) "news1"
3) "news2"
4) "news4"
5) "news5"
192.168.2.129:6379>
(6)sinter——求给定key对应的set交集
192.168.2.129:6379> sinter myset myset2
1) "news3"
192.168.2.129:6379>
(7)其他命令
命令 |
说明 |
srem |
删除key对应的set中的一个元素 |
sdiffstore |
求给定key对应的set与第一个key对应的set的差集,并存储到另一个key对应的set中 |
sinterstore |
求给定key对应的set交集,并存储到另一个key对应的set中 |
suionstore |
求给定key对应的set并集,并存储到另一个key对应的set中 |
somve |
从第一个key对应的set中删除指定元素并添加到第二个key对应的set中 |
scard |
返回key对应的set的元素个数 |
sismember |
测试某个元素是否为key对应的set中的元素个数 |
srandmember |
随机返回key对应的set中的一个元素,但不删除元素 |
SortSet
SortSet顾名思义,是一个排好序的Set,它在Set的基础上增加了一个顺序属性score,这个属性在添加修改元素时可以指定,每次指定后,SortSet会自动重新按新的值排序。
sorted set的内部使用HashMap和跳跃表(SkipList)来保证数据的存储和有序,HashMap里放的是成员到score的映射,而跳跃表里存放的是所有的成员,排序依据是HashMap里存的score。
应用场景
如按时间排序的时间轴。
常用命令
(1)zadd ——在key对应的zset中添加一个元素
(2)zrange——获取key对应的zset中指定范围的元素,-1表示获取所有元素
192.168.2.129:6379> zadd myzset 1 "one" 2 "two" 3 "three"
(integer) 3
192.168.2.129:6379> zrange myzset 0 -1
1) "one"
2) "two"
3) "three"
192.168.2.129:6379> zrange myzset 0 -1 withscores
1) "one"
2) "1"
3) "two"
4) "2"
5) "three"
6) "3"
192.168.2.129:6379>
(3)zrem——删除key对应的zset中的一个元素
192.168.2.129:6379> zrem myzset one
(integer) 1
192.168.2.129:6379> zrange myzset 0 -1 withscores
1) "two"
2) "2"
3) "three"
4) "3"
192.168.2.129:6379>
(4)其它命令
命令 |
说明 |
zincrby |
如果key对应的zset中已经存在元素member,则对member的score属性加指定的值 |
zrank |
返回key对应的zset中指定member的排名。其中member按score值递增(从小到大);排名以0为底,也就是说,score值最小的成员排名为0 |
zrevrank |
获得成员按score值递减(从大到小)排列的排名 |
zrevrange |
返回有序集key中,指定区间内的成员。其中成员的位置按score值递减(从大到小)来排列 |
zrangebyscore |
返回有序集key中,指定分数范围的元素列表 |
zcount |
返回有序集key中,score值在min和max之间(默认包括score值等于min或max)的成员 |
zcard |
返回key的有序集元素个数 |
Redis常用命令
键值常用命令
keys/exits/del/expire/ttl/move/persist/randomkey/rename/type
服务器常用命令
ping/echo/select/quit/dbsize/info/config get/flushdb/flushall
这些命令都很容易使用,就不举例说明了。到此,redis的数据类型以及常用命令已经介绍完毕,下一篇我们将学习redis的一些高级特性。
参考文档
http://www.redis.cn/documentation.html
http://blog.csdn.net/tonysz126/article/details/8280696/