Estructura de datos de Redis
Redis es un sistema de almacenamiento de valores clave. En comparación con Memcache, su valor admite más tipos de datos.
Redis utiliza objetos para identificar claves y valores en la base de datos. Siempre que se crea un par clave-valor en redis, se crean dos objetos: objetos clave y objetos de valor.
El objeto en Redis está representado por una estructura redisObject. Los tres atributos relacionados con guardar datos en esta estructura son: atributo de tipo, atributo de codificación y atributo ptr. como sigue:
typedef struct redisObject{
//类型
unsigned type:4;
//编码
unsigned encoding:4;
指向底层实现数据结构的指针
void *ptr;
}robj;
Uno, el tipo de datos de redis
El atributo type registra el tipo de objeto. El valor de este atributo puede ser una de las siguientes constantes:
Tipo constante | El nombre del objeto |
---|---|
REDIS_STRING | Objeto de cadena |
REDIS_LIST | Objeto de lista |
REDIS_HASH | Objeto hash |
REDIS_SET | Objeto de colección |
REDIS_ZSET | Colección ordenada de objetos |
Entre ellos, la clave de Redis es siempre un objeto de cadena y el valor puede ser uno de los cinco tipos de objetos anteriores.
Úselo TYPE key
para ver un valor de clave de base de datos de los tipos de datos de objeto, como:
redis> set name "zs"
OK
redis> TYPE name
"string"
Dos, realización de codificación redis
El atributo de codificación registra la codificación utilizada por el objeto, es decir, qué estructura de datos utiliza el objeto como implementación subyacente del objeto; el puntero ptr apunta a la estructura de datos de implementación subyacente del objeto.
Los objetos de Redis de cada tipo de datos usan codificaciones diferentes. La siguiente tabla enumera las codificaciones que puede usar cada tipo de objeto:
Tipos de | codificación | Objeto |
---|---|---|
REDIS_STRING | REDIS_ENCODING_INT | Objeto de cadena implementado usando valores enteros |
REDIS_STRING | REDIS_ENCODING_EMBSTR | Objeto de cadena realizado mediante el uso de cadena dinámica simple codificada en embstr |
REDIS_STRING | REDIS_ENCODING_RAW | Objeto de cadena implementado usando una cadena dinámica simple |
REDIS_LIST | REDIS_ENCODING_ZIPLIST | Objeto de lista implementado usando una lista comprimida |
REDIS_LIST | REDIS_ENCODING_LINKEDLIST | Objeto de lista implementado usando una lista enlazada de dos extremos |
REDIS_HASH | REDIS_ENCODING_ZIPLIST | Objeto hash implementado usando una lista comprimida |
REDIS_HASH | REDIS_ENCODING_HT | Objeto hash implementado usando diccionario |
REDIS_SET | REDIS_ENCODING_INTSET | Objetos de colección implementados usando colecciones de enteros |
REDIS_SET | REDIS_ENCODING_HT | Objeto de colección implementado usando diccionario |
REDIS_ZSET | REDIS_ENCODING_ZIPLIST | Objetos de colección ordenados implementados usando listas comprimidas |
REDIS_ZSET | REDIS_ENCODING_SKIPLIST | Colección ordenada de objetos implementada usando tablas de salto |
Úselo OBJECT ENCODING key
para ver el valor de los objetos de una base de datos de códigos clave, como:
redis> set name "zs"
OK
redis> OBJECT ENCODING name
"embstr"
La asociación de varios códigos para tipos específicos de objetos mejora en gran medida la flexibilidad y la eficiencia de Redis. Redis puede establecer diferentes códigos para un objeto de acuerdo con diferentes escenarios de uso, optimizando así la eficiencia del objeto en un determinado escenario. A continuación, presentaremos cómo cada tipo usa la codificación en diferentes escenarios.
3. Codificación y conversión de codificación de diferentes objetos
1. Objeto de cadena
La codificación de objetos de cadena puede ser int, raw, embstr.
- int: el objeto de cadena contiene un valor entero, y este valor entero se puede representar mediante el tipo largo;
- sin formato: el objeto de cadena almacena el valor de cadena y la longitud del valor de cadena es superior a 32 bytes;
- embstr: el objeto de cadena almacena el valor de la cadena y la longitud del valor de la cadena es menor o igual a 32 bytes;
(1) codificación int
Ejemplo:
redis> set number 10086
OK
redis> OBJECT ENCODING number
"int"
(2) Codificación sin formato
Ejemplo:
redis> set story "Long,long ago there lived a king..."
OK
redis> STRLEN story
(integer) 37
redis> OBJECT ENCODING story
"raw"
(3) codificación Embtsr
La codificación embstr es un método de codificación optimizado que se utiliza para guardar cadenas cortas. Esta codificación, como la codificación sin formato, utiliza la estructura redisObject y la estructura sdshdr para representar objetos de cadena, pero la codificación sin formato llama a la función de asignación de memoria dos veces para crearlos por separado. La estructura redisObject y la estructura sdshdr, mientras que la codificación embstr asigna un espacio continuo a través de una función de asignación de memoria, y el espacio contiene la estructura redisObject y la estructura sdshdr a su vez. Por lo tanto, la codificación embstr es más eficiente que la codificación sin formato en la asignación y liberación de memoria, y puede aprovechar mejor las ventajas del almacenamiento en caché.
Ejemplo:
redis> set msg "hello"
OK
redis> OBJECT ENCODING msg
"embstr"
(4) Conversión de código
Los objetos codificados en int y embstr se convertirán en objetos de cadena codificados sin formato cuando se cumplan las condiciones.
(a) Después de que se ejecutan algunos comandos para el objeto de cadena de codificación int, el objeto ya no es un valor entero, sino un valor de cadena, y la codificación cambiará de int a raw. Como:
redis> set number 10086
OK
redis> OBJECT ENCODING number
"int"
redis> APPEND number “ is a good number”
(integer) 23
redis> OBJECT ENCODING number
"raw"
(b) El objeto de cadena codificado por embstr es de solo lectura. Cuando ejecutamos cualquier comando de modificación en el objeto de cadena codificado por embstr, el programa primero convertirá la codificación del objeto de embstr a raw, y luego ejecutará el comando de modificación, entonces embstr El objeto de cadena codificado se convertirá en codificación sin formato después de la modificación. Como:
redis> set msg "hello"
OK
redis> OBJECT ENCODING msg
"embstr"
redis> APPEND msg " world"
(integer) 11
redis> OBJECT ENCODING msg
"raw"
2. Lista de objetos
La codificación del objeto de lista puede ser ziplist, linkedlist.
- ziplist: Al mismo tiempo: (1) La longitud de todos los elementos de cadena almacenados en el objeto de lista es inferior a 64 bytes; (2) El número de elementos almacenados en el objeto de lista es inferior a 512;
- Linkedlist: cuando no se cumple una de las dos condiciones anteriores, utilice la codificación de Linkedlist.
(1) codificación ziplist
Ejemplo:
redis> RPUSH numbers 1 "three" 5
(integer) 3
redis> OBJECT ENCODING numbers
"ziplist"
(2) Codificación de Linkedlist
Ejemplo:
redis> RPUSH numbers 1 "three" 5 .......
(integer) 513
redis> OBJECT ENCODING numbers
"linkedlist"
(3) Conversión de código
Para un objeto de lista que usa codificación ziplist, cuando no se puede cumplir alguna de las dos condiciones para usar la codificación ziplist, la codificación del objeto se convierte a lista vinculada.
3. Objetos hash
La codificación del objeto hash puede ser ziplist o hashtable.
- ziplist: Al mismo tiempo: (1) La longitud de las cadenas de clave y valor de todos los pares clave-valor almacenados en el objeto hash es menos de 64 bytes; (2) El número de pares clave-valor almacenados en el objeto hash no excede 512;
- Hashtable: cuando no se cumple una de las dos condiciones anteriores, se utiliza la codificación hashtable.
(1) codificación ziplist
Cuando se va a agregar un nuevo par clave-valor al objeto hash, el nodo de lista comprimida que almacena la clave se empuja al final de la tabla de lista comprimida, y luego el nodo de lista comprimido que almacena el valor se empuja al final de la tabla de lista comprimida.
Ejemplo:
redis> HSET profile name "Tom"
(integer) 1
redis> HSET profile age 25
(integer) 1
redis> HSET profile career "Programmerr"
(integer) 1
redis> OBJECT ENCODING numbers
"ziplist"
(2) codificación hashtable
El objeto hash codificado por tabla hash usa un diccionario como implementación subyacente, y cada par clave-valor en el objeto hash se almacena usando un par clave-valor de diccionario.
Ejemplo:
redis> HSET book "long_long_long_long_long_long...."
(integer) 1
redis> OBJECT ENCODING numbers
"hashtable"
(3) Conversión de código
Para un objeto hash que usa codificación ziplist, cuando no se puede cumplir alguna de las dos condiciones de codificación ziplist, la codificación del objeto se convierte en tabla hash.
4. Objetos de colección
La codificación del objeto de colección puede ser intset, hashtable.
- intset: Al mismo tiempo: (1) Todos los elementos almacenados en el objeto de colección son valores enteros; (2) El número de elementos almacenados en el objeto de colección no excede 512;
- Hashtable: cuando no se cumple una de las dos condiciones anteriores, se utiliza la codificación hashtable.
(1) codificación intset
Utilice la colección de enteros como la implementación subyacente, y todos los elementos contenidos en el objeto de colección se almacenan en la colección de enteros.
Ejemplo:
redis> SADD numbers 1 3 5
(integer) 3
redis> OBJECT ENCODING numbers
"intset"
(2) codificación hashtable
El objeto de colección codificado en tabla hash utiliza un diccionario como implementación subyacente.Cada clave del diccionario es una cadena y los valores del diccionario están todos configurados en NULL.
Ejemplo:
redis> SADD fruits "cherry" "apple" "banana"
(integer) 3
redis> OBJECT ENCODING fruits
"hashtable"
(3) Conversión de código
Para los objetos de colección que usan la codificación intset, cuando no se puede cumplir cualquiera de las dos condiciones para la codificación intset, la codificación del objeto se convertirá en tabla hash.
5. Colección ordenada de objetos
La codificación de objetos de conjuntos ordenados puede ser ziplist, skiplist.
- ziplist: Al mismo tiempo: (1) El número de elementos almacenados en el conjunto ordenado es menor a 128; (2) La longitud de todos los miembros de elementos almacenados en el conjunto ordenado es menor a 64 bytes;
- skiplist: cuando no se cumple una de las dos condiciones anteriores, se utiliza la codificación skiplist.
(1) codificación ziplist
El objeto de colección ordenado codificado con ziplist utiliza una lista comprimida como capa inferior. Cada elemento de colección se guarda utilizando dos nodos de lista comprimidos uno al lado del otro. El primer nodo almacena los miembros del elemento y el segundo elemento almacena la puntuación del elemento. . Los elementos del conjunto de la lista comprimida se organizan en orden descendente de puntuación. Los elementos con puntuaciones más pequeñas se colocan cerca de la cabecera de la tabla y los elementos con puntuaciones más grandes se colocan cerca del final de la tabla.
Ejemplo:
redis> ZADD price 8.5 apple 5.0 banana 6.0 cherry
(integer) 3
redis> OBJECT ENCODING price
"ziplist"
(2) Codificación de lista de omisiones
El objeto de colección ordenado codificado por skiplist utiliza zset como implementación subyacente. Una estructura zset contiene un diccionario (dict) y una lista de omisión (zsl).
La tabla de salto zsl guarda todos los elementos de la colección, de pequeños a grandes, según la puntuación. Cada nodo de la tabla de salto guarda un elemento de colección: el atributo de objeto de la tabla de salto almacena los miembros del elemento y el atributo de puntuación de la tabla de salto almacena la puntuación del elemento. A través de la lista de salto, puede realizar operaciones de rango en el conjunto ordenado. Por ejemplo, comandos como ZRANK y ZRANGE se implementan según la API de lista de salto.
El diccionario dict crea un mapeo de miembros a puntuaciones para un conjunto ordenado. Cada par clave-valor del diccionario almacena un elemento de conjunto: la clave del diccionario almacena los miembros del elemento y el valor del diccionario almacena la puntuación del elemento. A través del diccionario, el programa puede buscar la puntuación de un miembro dado con complejidad O (1), como el comando ZSCORE.
Ejemplo:
redis> ZCARD numbers
(integer) 128
redis> OBJECT ENCODING numbers
"ziplist"
redis> ZADD numbers 3.14 pi
(integer) 1
redis> ZCARD numbers
(integer) 129
redis> OBJECT ENCODING numbers
"skiplist"
(3) Conversión de código
Para un conjunto ordenado de objetos codificados mediante ziplist, cuando no se puede cumplir cualquiera de las dos condiciones de codificación mediante ziplist, la codificación del objeto se convertirá en skiplist.
Cuatro, referencias
[1]: "Diseño e implementación de Redis" Parte uno Estructura de datos y objetos