Overview, data type, data structure, usage scenario of Redis

1. Overview

Redis is a very fast, non-relational (NoSQL) memory key-value database that stores mappings between keys and five different types of values.

Keys can only be of type string, and values support five data types: string, list, collection, hash, ordered collection.

Redis supports many features, such as persistence of in-memory data to hard drives, replication to extend read performance, and fragmentation to extend write performance.

2. Data Types

data type Values that can be stored operation
STRING String, integer, or floating point number Perform operations on an entire string or part of a string
Perform auto-increment or auto-decrement operations on integers and floating-point numbers
LIST list Push or eject elements from both ends
Trimming a single or multiple element,
Keep only elements within a range
SET unordered set Add, get, remove individual elements
Check if an element exists in a collection
Compute intersection, union, difference
Randomly fetch elements from a set
HASH Unordered Hash list containing key-value pairs Add, Get, Remove Single Key-Value Pairs
Get all key-value pairs
Check if a key exists
ZSET Ordered Set Add, get, delete elements
Get elements based on scoring ranges or members
Calculate the rank of a key
//STRING

> set hello world
OK
> get hello
"world"
> del hello
(integer) 1
> get hello
(nil)

//LIST
> rpush list-key item
(integer) 1
> rpush list-key item2
(integer) 2
> rpush list-key item
(integer) 3

> lrange list-key 0 -1
1) "item"
2) "item2"
3) "item"

> lindex list-key 1
"item2"

> lpop list-key
"item"

> lrange list-key 0 -1
1) "item2"
2) "item"

//SET
> sadd set-key item
(integer) 1
> sadd set-key item2
(integer) 1
> sadd set-key item3
(integer) 1
> sadd set-key item
(integer) 0

> smembers set-key
1) "item"
2) "item2"
3) "item3"

> sismember set-key item4
(integer) 0
> sismember set-key item
(integer) 1

> srem set-key item2
(integer) 1
> srem set-key item2
(integer) 0

> smembers set-key
1) "item"
2) "item3"


//HASH
> hset hash-key sub-key1 value1
(integer) 1
> hset hash-key sub-key2 value2
(integer) 1
> hset hash-key sub-key1 value1
(integer) 0

> hgetall hash-key
1) "sub-key1"
2) "value1"
3) "sub-key2"
4) "value2"

> hdel hash-key sub-key2
(integer) 1
> hdel hash-key sub-key2
(integer) 0

> hget hash-key sub-key1
"value1"

> hgetall hash-key
1) "sub-key1"
2) "value1"



//ZSET
> zadd zset-key 728 member1
(integer) 1
> zadd zset-key 982 member0
(integer) 1
> zadd zset-key 982 member0
(integer) 0

> zrange zset-key 0 -1 withscores
1) "member1"
2) "728"
3) "member0"
4) "982"

> zrangebyscore zset-key 0 800 withscores
1) "member1"
2) "728"

> zrem zset-key member1
(integer) 1
> zrem zset-key member1
(integer) 0

> zrange zset-key 0 -1 withscores
1) "member0"
2) "982"

HASH structure

ZSET structure

3. Data structure

1) Dictionary

dictht is a hash structure that uses zipper to resolve hash conflicts.

/* This is our hash table structure. Every dictionary has two of this as we
 * implement incremental rehashing, for the old to the new table. */
typedef struct dictht {
    dictEntry **table;
    unsigned long size;
    unsigned long sizemask;
    unsigned long used;
} dictht;

typedef struct dictEntry {
    void *key;
    union {
        void *val;
        uint64_t u64;
        int64_t s64;
        double d;
    } v;
    struct dictEntry *next;
} dictEntry;

Redis's dictionary dictht contains two hash tables, dictht, for easy rehash operation.When expanding capacity, rehash the key-value pair on one dictht onto the other dictht, then free up space and swap the roles of the two dicthts.

typedef struct dict {
    dictType *type;
    void *privdata;
    dictht ht[2];
    long rehashidx; /* rehashing not in progress if rehashidx == -1 */
    unsigned long iterators; /* number of iterators currently running */
} dict;

The rehash operation is not a one-time operation, but rather a gradual one-time operation to avoid overburdening the server by performing too many rehash operations at once.

Incremental rehash is done by recording the rehashidx of dict, which starts at 0 and increments with each execution of rehash.For example, in a rehash, to rehash dict[0] rehash to dict[1], this time rehash the key pair of table[rehashidx] on dict[0] to dict[1], table[rehashidx] of dict[0] to null, and rehashidx++.

During rehash, an incremental rehash is performed every time a dictionary is added, deleted, found, or updated.

Using progressive rehash causes the data in the dictionary to be spread over two dicthts, so the dictionary lookup operation also needs to be performed on the corresponding dictht.

2) Jump Table

Is one of the underlying implementations of ordered collections.

A skip table is based on a multi-pointer ordered list, which can be viewed as multiple ordered lists.

 

When searching, start with the upper pointer, find the corresponding interval, and then go to the next level.The following figure demonstrates the process of finding 22.

 

Compared with balance trees such as red-black trees, jump tables have the following advantages:

  • Insertion speed is very fast because there is no need to rotate or other operations to maintain balance;
  • Easier to implement;
  • Supports lock-free operations.

4. Scenes of use

1) Counter

String can be self-increasing and self-decreasing to achieve counter function.

Redis is an in-memory database with very high read and write performance and is ideal for storing counts of frequent reads and writes.

2) Cache

Put hot spot data in memory, set the maximum amount of memory used, and phase out policy to ensure the hit rate of the cache.

3) Lookup table

For example, DNS records are well suited for storage using Redis.

Lookup tables are similar to caches in that they take advantage of Redis's fast lookup feature.However, the contents of the lookup table cannot be invalidated, and the contents of the cache can be invalidated because the cache is not a reliable data source.

4) Message Queue

List is a two-way chain table that can write and read messages through lpush and rpop

However, it is best to use messaging middleware such as Kafka, RabbitMQ, and so on.

5) Session Cache

You can use Redis to unify session information across multiple application servers.

When an application server no longer stores user session information, it no longer has a state, and a user can request any application server, making it easier to achieve high availability and scalability.

6) Distributed Lock Implementation

In distributed scenarios, locks in a single machine environment cannot be used to synchronize processes on multiple nodes.

Distributed locks can be implemented using Redis's own SETNX command, in addition to the official RedLock distributed locks.

7) Other

Set implements operations such as intersection, union, and so on, enabling functions such as mutual friends.

ZSet implements orderliness to achieve rankings and other functions.

70 original articles published. Praise 5. Visits 4459
Private letter follow

Tags: Redis Session Database DNS

Posted on Fri, 07 Feb 2020 19:05:34 -0800 by digibrain