Introdução ao Redis, começando com a estrutura de dados subjacente e os princípios do aplicativo

índice

Um, conheça Redis

Dois, Redis 5 tipos de big data

Três, análise da estrutura de dados subjacente do Redis SDS

Quatro, análise de estrutura de dados de lista vinculada

Cinco, lista a estrutura de dados

1. Lista compactada

2. Lista rápida

Seis, dicionário Redis

Sete, coleção de inteiros do Redis

Oito, mesa de salto Redis

Nove, objeto Redis

Dez, cenários de uso do Redis


Um, conheça Redis

Recentemente comecei a aprender banco de dados Redis, aprender com o conteúdo mais simples, e depois resumir e gravar aqui, caso você esqueça, e compartilhar com todos!

A instalação do Windows é mostrada na figura:

Link para Download:

Windows :https://github.com/microsoftarchive/redis/releases/download/win-3.2.100/Redis-x64-3.2.100.zip

Linux :http://download.redis.io/releases/redis-6.0.6.tar.gz

Lado do servidor:

Lado do cliente:

Como um banco de dados NoSQL de código aberto de alto desempenho, o Redis armazena principalmente dados na forma de pares de valores-chave, desenvolvidos em linguagem C, e adota o protocolo BSD. Tem funções poderosas e oferece suporte a vários tipos de dados. banco de dados relacional.

É diferente de bancos de dados relacionais como Mysql, SQLServer e Oracle. Portanto, as características do Redis lhe conferem muitas vantagens:

  1. Suporta várias linguagens de programação, como Java, C, C ++, Python, PHP, Go, Lua, etc .;
  2. Incluindo tipos de dados ricos, como String, List, Set, Hash, Sorted Set;
  3. Velocidade de leitura e gravação rápida e alto desempenho. Dados oficiais: velocidade de leitura 110000 vezes / s, velocidade de escrita 81000 vezes / s, o que significa que os dados são armazenados na memória para leitura e escrita;
  4. Persistência. O recurso importante do Redis é obter persistência, salvar os dados na memória no disco regularmente e carregá-los na memória novamente ao reiniciar o servidor. Existem AOF e RDB para persistência;
  5. Simples e poderoso. Pode realizar publicação de assinatura de notícias, script Lua, transação de banco de dados, etc. Redis é um trabalho de thread único, todas as operações são atômicas e simples de usar.
  6. Realize a replicação mestre-escravo de alta disponibilidade.
  7. Perceba cluster distribuído e alta disponibilidade, respectivamente Redis Cluster e Redis Sentinel.
  8. Suporta múltiplas estruturas de dados. Tal Hash, Set, bitmap, etc.

A seguir, uma breve introdução dos cinco tipos de dados do Redis.

Dois, Redis 5 tipos de big data

Os comandos de operação específicos dos 5 tipos de big data do Redis podem ser encontrados em: http://www.redis.cn/commands.html

1. Corda

Strings são o tipo de dados mais básico no Redis e são binários seguros. A chave do tipo String pode armazenar até 512M de dados.

Os dados suportados incluem: dados binários, dados serializados, objetos JSONized, etc.

2. Hash

O tipo Hash é uma tabela de mapeamento de campos e valores do tipo String, comumente usada para armazenar informações de objetos. Cada tabela hash pode armazenar 2 ^ 32-1 pares de valor-chave, o que equivale a 4 bilhões de dados.

3. Lista

A lista Redis é equivalente a uma lista de strings simples, classificada na ordem de inserção, e um elemento pode ser inserido no início ou no final da tabela. O mesmo pode armazenar 2 ^ 32-1 elementos.

4. Definir

O tipo de dados Set é uma coleção não ordenada do tipo String e cada elemento é único. A coleta é realizada por meio de uma tabela hash, com alta eficiência de adição, exclusão e complexidade O (1). A capacidade máxima de uma coleção é armazenar 2 ^ 32-1 elementos.

5. Classificação Classificada

Uma coleção ordenada é uma coleção do tipo String, em que cada elemento corresponde a um valor do tipo double. O Redis classifica os elementos de acordo com o tamanho desse valor, que também é implementado por meio de uma tabela hash, com alta eficiência de adição, exclusão e complexidade O (1). A capacidade máxima de uma coleção é armazenar 2 ^ 32-1 elementos.

Três, análise da estrutura de dados subjacente do Redis SDS

O Redis é escrito na linguagem C e a implementação subjacente tem a gramática e as características da linguagem C. O tipo de string em C não é usado diretamente, mas o tipo SDS (string dinâmica simples) é construído por si mesmo como a string padrão do Redis.

Parte SDS do código-fonte:

struct __attribute__ ((__packed__)) sdshdr5 {
    unsigned char flags; /* 3 lsb of type, and 5 msb of string length */
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr8 {
    uint8_t len; /* used */
    uint8_t alloc; /* excluding the header and null terminator */
    unsigned char flags; /* 3 lsb of type, 5 unused bits */
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr16 {
    uint16_t len; /* used */
    uint16_t alloc; /* excluding the header and null terminator */
    unsigned char flags; /* 3 lsb of type, 5 unused bits */
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr32 {
    uint32_t len; /* used */
    uint32_t alloc; /* excluding the header and null terminator */
    unsigned char flags; /* 3 lsb of type, 5 unused bits */
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr64 {
    uint64_t len; /* used */
    uint64_t alloc; /* excluding the header and null terminator */
    unsigned char flags; /* 3 lsb of type, 5 unused bits */
    char buf[];
};

Pode-se ver no código subjacente que uma variedade de estruturas são definidas para se adaptar às diferentes necessidades.

A diferença entre string C e SDS:

  1. A API de string de C é binária insegura. Pode haver um estouro de buffer. Apenas dados de texto podem ser salvos. Todas as funções de biblioteca de string.h podem ser usadas. Depois que o comprimento é modificado, a memória é alocada uma vez. A complexidade de tempo para obter o o comprimento da string é O (n).
  2. SDS API é binário seguro, não há estouro de buffer, você pode salvar texto / dados binários, usar algumas funções de biblioteca de string.h, modificar o comprimento de N vezes e alocar tempos de memória <= N, obter o comprimento para O (1 )

Quatro, análise de estrutura de dados de lista vinculada

/* Node, List, and Iterator are the only data structures used currently. */

typedef struct listNode {
    struct listNode *prev;
    struct listNode *next;
    void *value;
} listNode;

typedef struct listIter {
    listNode *next;
    int direction;
} listIter;

typedef struct list {
    listNode *head;
    listNode *tail;
    void *(*dup)(void *ptr);
    void (*free)(void *ptr);
    int (*match)(void *ptr, void *key);
    PORT_ULONG len;
} list;

 Não há uma estrutura de lista vinculada integrada na linguagem C. O Redis cria uma lista vinculada por si mesmo. Ele usa uma lista duplamente vinculada. Consiste em vários nós distribuídos discretamente conectados por ponteiros. Cada nó tem um nó predecessor e um nó sucessor , exceto para o nó principal (sem predecessor) e o nó final (sem sucessor).

Cinco, lista a estrutura de dados

1. Lista compactada


#ifndef _ZIPLIST_H
#define _ZIPLIST_H

#define ZIPLIST_HEAD 0
#define ZIPLIST_TAIL 1

unsigned char *ziplistNew(void);
unsigned char *ziplistMerge(unsigned char **first, unsigned char **second);
unsigned char *ziplistPush(unsigned char *zl, unsigned char *s, unsigned int slen, int where);
unsigned char *ziplistIndex(unsigned char *zl, int index);
unsigned char *ziplistNext(unsigned char *zl, unsigned char *p);
unsigned char *ziplistPrev(unsigned char *zl, unsigned char *p);
unsigned int ziplistGet(unsigned char *p, unsigned char **sval, unsigned int *slen, PORT_LONGLONG *lval);
unsigned char *ziplistInsert(unsigned char *zl, unsigned char *p, unsigned char *s, unsigned int slen);
unsigned char *ziplistDelete(unsigned char *zl, unsigned char **p);
unsigned char *ziplistDeleteRange(unsigned char *zl, int index, unsigned int num);
unsigned int ziplistCompare(unsigned char *p, unsigned char *s, unsigned int slen);
unsigned char *ziplistFind(unsigned char *p, unsigned char *vstr, unsigned int vlen, unsigned int skip);
unsigned int ziplistLen(unsigned char *zl);
size_t ziplistBlobLen(unsigned char *zl);

#ifdef REDIS_TEST
int ziplistTest(int argc, char *argv[]);
#endif

#endif /* _ZIPLIST_H */

 A lista compactada do Redis é implementada pela camada inferior da chave da lista e da chave hash.

Quando a lista contém menos elementos e o valor é menor, o Redis usa uma lista compactada para implementá-la, que é uma estrutura de dados sequencial.

2. Lista rápida

A lista rápida é uma lista duplamente vinculada composta de listas compactadas e cada nó da lista vinculada salva dados em uma lista compactada.

A lista é definida da seguinte forma:

typedef struct quicklist {
    quicklistNode *head;
    quicklistNode *tail;
    PORT_ULONG count;        /* total count of all entries in all ziplists */
    unsigned int len;           /* number of quicklistNodes */
    int fill : 16;              /* fill factor for individual nodes */
    unsigned int compress : 16; /* depth of end nodes not to compress;0=off */
} quicklist;

Nó da lista rápida:

typedef struct quicklistNode {
    struct quicklistNode *prev;
    struct quicklistNode *next;
    unsigned char *zl;
    unsigned int sz;             /* ziplist size in bytes */
    unsigned int count : 16;     /* count of items in ziplist */
    unsigned int encoding : 2;   /* RAW==1 or LZF==2 */
    unsigned int container : 2;  /* NONE==1 or ZIPLIST==2 */
    unsigned int recompress : 1; /* was this node previous compressed? */
    unsigned int attempted_compress : 1; /* node can't compress; too small */
    unsigned int extra : 10; /* more bits to steal for future usage */
} quicklistNode;

 

Seis, dicionário Redis

O dicionário Redis é uma estrutura de dados usada para armazenar pares de valores-chave do Redis. Também é construído pelo próprio Redis. A camada inferior do banco de dados Redis também é implementada por um dicionário, e a operação CURD é construída no dicionário.


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

typedef struct dictType {
    unsigned int (*hashFunction)(const void *key);
    void *(*keyDup)(void *privdata, const void *key);
    void *(*valDup)(void *privdata, const void *obj);
    int (*keyCompare)(void *privdata, const void *key1, const void *key2);
    void (*keyDestructor)(void *privdata, void *key);
    void (*valDestructor)(void *privdata, void *obj);
} dictType;

/* 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;
    PORT_ULONG size;
    PORT_ULONG sizemask;
    PORT_ULONG used;
} dictht;

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

 

Sete, coleção de inteiros do Redis

Quando uma coleção contém apenas elementos com valor inteiro e o número de elementos é pequeno, o Redis usa essa estrutura de dados para implementar a camada inferior da chave da coleção.


#ifndef __INTSET_H
#define __INTSET_H
#include <stdint.h>

typedef struct intset {
    uint32_t encoding;
    uint32_t length;
    int8_t contents[];
} intset;

intset *intsetNew(void);
intset *intsetAdd(intset *is, int64_t value, uint8_t *success);
intset *intsetRemove(intset *is, int64_t value, int *success);
uint8_t intsetFind(intset *is, int64_t value);
int64_t intsetRandom(intset *is);
uint8_t intsetGet(intset *is, uint32_t pos, int64_t *value);
uint32_t intsetLen(intset *is);
size_t intsetBlobLen(intset *is);

#ifdef REDIS_TEST
int intsetTest(int argc, char *argv[]);
#endif

#endif // __INTSET_H

Oito, mesa de salto Redis

A tabela de salto é uma estrutura de dados ordenada que oferece suporte à busca rápida de nós e ao processamento em lote de nós. Se o conjunto ordenado tiver muitos elementos e o valor do elemento for uma string longa, o Redis usará uma tabela de salto como a implementação subjacente do conjunto ordenado.

Nove, objeto Redis

A estrutura de dados do Redis acima não é usada diretamente, mas um sistema de objetos é criado, incluindo objetos de string, objetos de lista e assim por diante. O sistema Red is object implementa um mecanismo de reciclagem de memória baseado na tecnologia de contagem de referência.Quando um objeto não está em uso, o sistema irá automaticamente recuperar o espaço de memória ocupado pelo objeto.

robj *dupStringObject(robj *o) {
    robj *d;

    serverAssert(o->type == OBJ_STRING);

    switch(o->encoding) {
    case OBJ_ENCODING_RAW:
        return createRawStringObject(o->ptr,sdslen(o->ptr));
    case OBJ_ENCODING_EMBSTR:
        return createEmbeddedStringObject(o->ptr,sdslen(o->ptr));
    case OBJ_ENCODING_INT:
        d = createObject(OBJ_STRING, NULL);
        d->encoding = OBJ_ENCODING_INT;
        d->ptr = o->ptr;
        return d;
    default:
        serverPanic("Wrong encoding.");
        break;
    }
}

robj *createQuicklistObject(void) {
    quicklist *l = quicklistCreate();
    robj *o = createObject(OBJ_LIST,l);
    o->encoding = OBJ_ENCODING_QUICKLIST;
    return o;
}

robj *createZiplistObject(void) {
    unsigned char *zl = ziplistNew();
    robj *o = createObject(OBJ_LIST,zl);
    o->encoding = OBJ_ENCODING_ZIPLIST;
    return o;
}

robj *createSetObject(void) {
    dict *d = dictCreate(&setDictType,NULL);
    robj *o = createObject(OBJ_SET,d);
    o->encoding = OBJ_ENCODING_HT;
    return o;
}

robj *createIntsetObject(void) {
    intset *is = intsetNew();
    robj *o = createObject(OBJ_SET,is);
    o->encoding = OBJ_ENCODING_INTSET;
    return o;
}

robj *createHashObject(void) {
    unsigned char *zl = ziplistNew();
    robj *o = createObject(OBJ_HASH, zl);
    o->encoding = OBJ_ENCODING_ZIPLIST;
    return o;
}

robj *createZsetObject(void) {
    zset *zs = zmalloc(sizeof(*zs));
    robj *o;

    zs->dict = dictCreate(&zsetDictType,NULL);
    zs->zsl = zslCreate();
    o = createObject(OBJ_ZSET,zs);
    o->encoding = OBJ_ENCODING_SKIPLIST;
    return o;
}

robj *createZsetZiplistObject(void) {
    unsigned char *zl = ziplistNew();
    robj *o = createObject(OBJ_ZSET,zl);
    o->encoding = OBJ_ENCODING_ZIPLIST;
    return o;
}

Dez, cenários de uso do Redis

Depois de falar sobre tantos pontos de conhecimento teórico do Redis, como perceber as vantagens?

Em aplicações práticas, todos os principais sites e sistemas podem apresentar o Redis, e ele é amplamente utilizado, o que resolve os problemas que os bancos de dados relacionais não podem resolver.

Cenários de uso do Redis:

  1. Faça cache. O cenário de uso mais comum do Redis. Ele não precisa gerar dados novamente todas as vezes, e a velocidade do cache e a velocidade da consulta são rápidas. Armazene conteúdo de notícias, informações de produtos ou carrinhos de compras etc.
  2. Faça um contador. As operações do Redis são atômicas. Pode ser usado para registrar o número de repostagens e comentários.
  3. Perceba o sistema de fila de mensagens. Suporte a correspondência de padrões, que pode realizar assinatura e publicação de notícias. Os comandos de fila de bloqueio podem realizar atividades como compra de pico e pânico.
  4. Sistema em tempo real, sistema de mensagem. A função definida do Redis pode ser usada para visualizar as operações específicas do usuário e realizar um sistema em tempo real.
  5. Classificações de bilhões de níveis. Este também é um aplicativo importante do Redis, que usa coleções ordenadas para classificar centenas de milhões de usuários em tempo real, graças à velocidade de leitura e gravação do Redis.
  6. Grande rede social. Como QQ, Weibo, etc., os usuários precisam do suporte Redis para navegar e bater papo.

Este artigo é a introdução recente da Xiaobai ao aprendizado do banco de dados Redis, aprendendo registros a partir do conteúdo mais simples e compartilhando-o com todos! Como um banco de dados NoSQL de código aberto de alto desempenho, o Redis é diferente dos bancos de dados relacionais, como Mysql, SQLServer e Oracle. Portanto, as características do Redis lhe conferem muitas vantagens. Existem muitos lugares importantes que não estão registrados aqui, como os princípios de implementação específicos de persistência AOF, RDB, cluster Redis, etc., depois de aprender mais tarde, estarei livre para registrar!

Se você acha que é bom, bem-vindo ao "um clique, três links", goste, marque, siga, comente diretamente se tiver alguma dúvida, troque e aprenda! 


Meu blog CSDN: https://blog.csdn.net/Charzous/article/details/114546348

Acho que você gosta

Origin blog.csdn.net/Charzous/article/details/114546348
Recomendado
Clasificación