Redis from entry to abandonment series (1) String

Redis from entry to abandonment series (1) String

The example in this article is based on: 5.0.4 String is the most common data structure in Redis, and the bottom layer is SDS, which is a string that can be modified, similar to ArrayList, which uses pre-allocated redundant space to reduce frequent memory allocation.

First let's see how to use the string type in redis

// 将字符串 value 关联到 key
// 如果key 已经有值了,直接覆盖 emmmm.跟我们使用HashMap是不是很像~
// 如果已经存在一个带有过期时间的key,我们重新set会将原先的过期时间清除 (重点)
>set key value [expiration EX seconds|PX milliseconds] [NX|XX]

Optional parameters: [expiration EX seconds|PX milliseconds] [NX|XX]

We found that the set method has two optional parameters [expiration EX seconds|PX milliseconds] and [NX|XX]

>EX seconds:将键的过期时间设置为 seconds 秒。 执行 SET key value EX seconds 的效果等同于执行 SETEX key seconds value 
>PX milliseconds:将键的过期时间设置为 milliseconds 毫秒。 执行 SET key value PX milliseconds 的效果等同于执行 PSETEX key milliseconds value
>NX:只在键不存在时, 才对键进行设置操作。 执行 SET key value NX 的效果等同于执行 SETNX key value
>XX:只在键已经存在时, 才对键进行设置操作

##Code example:

//对不存在的健设置
>set name "black-search"
OK
>get name 
"black-search"
----------------------------------
//对已经存在的值设置
>set name "new-black-search"
OK
>get name
"new-black-search"
----------------------------------
//使用 ex seconds 
>set name "black-search" ex 10
OK
>get name
"black-search"
//获取key的有效时间
>ttl name 
(integer) 6
//稍微等一会再执行下面的命令
>get name 
(nil)
----------------------------------
// 使用nx
>set name "black-search" nx
OK
>set name "black-search" nx
(nil)
----------------------------------
// 使用xx
>set name "new-black-search" xx
OK
//让我们设置一个不存在的key
>set key value xx
(nil)

setSo far, the usage of redis has come to an end.


debug object key

When we use redis for ordinary setprocessing, we will use the following way to set:

>set name "black-search"
OK
// redis提供的调试 api
>debug object name
Value at:0x179d060 refcount:1 encoding:embstr serializedlength:13 lru:14160370 lru_seconds_idle:17

From the above output, let's focus on it serializedlength:13. The length of our input is only 12. Why does it output 13? In fact, redis helped us do the processing. Redis will use '\0' at the end of the character.

Because the traditional C string conforms to the ASCII encoding, the operation of this encoding is characterized by: stop when it encounters zero. That is, when reading a string, as long as the end of '\0' is encountered, it is considered that the end is reached, and all characters after the end of '\0' are ignored. Therefore, if the traditional string saves binary files such as pictures, videos, etc., it will be truncated when the file is manipulated, so is the reader doing the same as me here?

127.0.0.1:6379> set name "ssssssss\0 asdasdasdasd"
OK
127.0.0.1:6379> get name
"ssssssss0 asdasdasdasd"
127.0.0.1:6379> set name "asdasdasd \\0 asdasdasdasd "
OK
127.0.0.1:6379> get name
"asdasdasd \\0 asdasdasdasd "
127.0.0.1:6379> set name "asdasdasd'\0' asdasdasdasdasd"
OK
127.0.0.1:6379> get name
"asdasdasd'0' asdasdasdasdasd"
127.0.0.1:6379> set name "asdasdasd '\\0'asdasdasd"
OK
127.0.0.1:6379> get name
"asdasdasd '\\0'asdasdasd"

Haha, in fact, redis has been filtered here~

sds sdscatrepr(sds s, const char *p, size_t len) {
    s = sdscatlen(s,"\"",1);
    while(len--) {
        switch(*p) {
        case '\\':
        case '"':
            s = sdscatprintf(s,"\\%c",*p);
            break;
        case '\n': s = sdscatlen(s,"\\n",2); break;
        case '\r': s = sdscatlen(s,"\\r",2); break;
        case '\t': s = sdscatlen(s,"\\t",2); break;
        case '\a': s = sdscatlen(s,"\\a",2); break;
        case '\b': s = sdscatlen(s,"\\b",2); break;
        default:
            if (isprint(*p))
                s = sdscatprintf(s,"%c",*p);
            else
                s = sdscatprintf(s,"\\x%02x",(unsigned char)*p);
            break;
        }
        p++;
    }
    return sdscatlen(s,"\"",1);
}

back to beginning

We say that strings are similar to Java's ArrayList, so how does it expand each time?

//sds.h
#define SDS_MAX_PREALLOC (1024*1024)
//sds.c
sds sdsMakeRoomFor(sds s, size_t addlen) {
    void *sh, *newsh;
    size_t avail = sdsavail(s);
    size_t len, newlen;
    char type, oldtype = s[-1] & SDS_TYPE_MASK;
    int hdrlen;

    /* Return ASAP if there is enough space left. */
    if (avail >= addlen) return s;

    len = sdslen(s);
    sh = (char*)s-sdsHdrSize(oldtype);
    newlen = (len+addlen);
    if (newlen < SDS_MAX_PREALLOC)
        newlen *= 2;
    else
        newlen += SDS_MAX_PREALLOC;

    type = sdsReqType(newlen);

    /* Don't use type 5: the user is appending to the string and type 5 is
     * not able to remember empty space, so sdsMakeRoomFor() must be called
     * at every appending operation. */
    if (type == SDS_TYPE_5) type = SDS_TYPE_8;

    hdrlen = sdsHdrSize(type);
    if (oldtype==type) {
        newsh = s_realloc(sh, hdrlen+newlen+1);
        if (newsh == NULL) return NULL;
        s = (char*)newsh+hdrlen;
    } else {
        /* Since the header size changes, need to move the string forward,
         * and can't use realloc */
        newsh = s_malloc(hdrlen+newlen+1);
        if (newsh == NULL) return NULL;
        memcpy((char*)newsh+hdrlen, s, len+1);
        s_free(sh);
        s = (char*)newsh+hdrlen;
        s[-1] = type;
        sdssetlen(s, len);
    }
    sdssetalloc(s, newlen);
    return s;
}

As can be seen from the above code, when the length of the string is less than 1M, the existing space is doubled for expansion. If it exceeds 1M, only 1M more space will be expanded at a time during expansion. (The maximum length of the string is 512M)

Application scenarios

1. Store business data

>set user:1 '{"id":1,"name":"黑搜丶D","wechat":"black-search"}'

2. Self-incrementing ID When the value of value is an integer type, redis can perform the self-increment (incr) and self-decrease (decr) operations as if it were an integer. Since all operations of redis are atomic, there is no need to worry about transaction problems that may occur when multiple clients are connected.

black search, D

{{o.name}}
{{m.name}}

Guess you like

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