Distributed caching technology redis learning series (2) - detailed explanation of redis data structure (memory model) and common commands

 

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/

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324790596&siteId=291194637