Jugabilidad avanzada de redis zset

Prefacio

Recientemente, los blogueros han recibido una solicitud de clasificación que nos obliga a clasificar a los usuarios según su peso, estado, sexo y estado en línea y fuera de línea. Según nuestra base de datos tradicional, no funciona, porque si quiero ordenar, necesito sacar todos los datos para ordenar. ¿Qué pasa si tengo una gran cantidad de datos en este momento? No puedo sacarlos todos y ordenarlos por Java, el rendimiento es muy bajo. Entonces algunos amigos definitivamente dirán, use zset para ordenar directamente. Entonces, todos sabemos que zset se ordena por puntaje, pero ¿cómo colocamos la clasificación de pesos múltiples en zset?

Tecnología del núcleo

En primer lugar, de acuerdo con las cuatro dimensiones de peso, estado, sexo y estado en línea de mi usuario, primero démosle prioridad según sus necesidades. En primer lugar, no hace falta decir que el estado tiene la máxima prioridad, seguido del género, luego el estado en línea y fuera de línea en la sala y, finalmente, el peso del usuario.
Estado> Sexo> En línea y fuera de línea en el estado de la habitación> Peso del usuario.
Entonces tenemos dos enfoques. 1: Método de división decimal. 2: Método de división binaria.

División decimal

Esto es muy fácil de entender. Es dividir nuestra condición en dígitos irrazonables a través de números enteros decimales y, finalmente, cuanto mayor sea la prioridad, mayores serán los dígitos. Por ejemplo, mi usuario tiene el peso más pequeño, pero tiene 10 pesos. Entonces puedo poner nuestro 10 en el décimo lugar. Cuando se sacan de esta manera, se clasifican según el peso.
Por ejemplo,
Inserte la descripción de la imagen aquí
nuestra primera condición ya es buena. Aquí hay un recordatorio, antes de hacer la clasificación, primero debemos pensar en la prioridad condicional y finalmente clasificar la prioridad por nosotros mismos. Lo hacemos primero de acuerdo con la prioridad más baja, para que la puntuación final calculada esté en el orden correcto. .
Entonces, la segunda condición es el estado en línea del usuario. Entonces solo hay tres estados en línea. Como mi decil ya está ocupado, usaré el percentil en su lugar. 100 está desconectado, 200 está conectado y 300 está en la sala. Al final, nuestra puntuación se ha convertido en la siguiente:
Inserte la descripción de la imagen aquí
y así sucesivamente, también se pueden reproducir otros valores de condición de esta manera. Luego, cuando calculamos las puntuaciones de acuerdo con la prioridad condicional y las almacenamos en zset, ya es un conjunto que nos ayuda a ordenar el orden, solo necesitamos usarlo. El primero es muy sencillo y fácil de entender. A continuación, quiero hablar sobre la segunda versión avanzada.

División binaria

Primero, comprendamos primero la estructura de la tabla de salto de zset:

typedef struct zskiplistNode {
    
    
    
        // 成员对象
        robj *obj;
    
        // 分值
        double score;
    
        // 后退指针
        struct zskiplistNode *backward;
    
        // 层
        struct zskiplistLevel {
    
    
            // 前进指针
            struct zskiplistNode *forward;
    
            // 跨度
            unsigned int span;
        } level[];
    
    } zskiplistNode;

Podemos ver que su puntuación es en realidad un dato de tipo double. Entonces, primero entendamos su doble.
Primero, su tipo doble es un número de coma flotante doble estándar IEEE 754. De esto podemos conocer su estructura
Inserte la descripción de la imagen aquí

S: el bit de signo 1 es un número negativo, 0 es un número positivo
Exp: se refiere a un número, el segundo párrafo, ocupa 11 bits, el método de cambio de código representa números positivos y negativos, excluyendo el caso especial de todo 0 y todo 1 que representa cero e infinito, la parte exponente −1022 ~ + 1023 más 1023, el tamaño del exponente es de 1 ~ 2046
Fracción: Dígitos significativos, 52 dígitos, número de coma fija, el punto decimal se coloca al frente de la mantisa.
Después de saber esto, podemos usar diferentes según diferentes condiciones. Número de bits para acceder a los datos. Luego, debido a que los bloggers tienen menos condiciones, se usa el tipo int para almacenar nuestros datos.
En primer lugar, necesito averiguar cuántas posiciones se necesitan para cada condición.

  1. Peso de usuario: porque solo hay 10 pesos de usuario. Entonces, cuando convierto 10 a binario, es 1010, que ocupa 4 dígitos, por lo que almacenamos el peso del usuario en los 4 dígitos inferiores del valor de tipo int como se muestra en la siguiente figura: En
    Inserte la descripción de la imagen aquí
    este momento, aunque usamos representación binaria, pero en En redis, le mostrará el valor decimal, que es 10. Luego regrese a la división decimal de la que acabamos de hablar.De hecho, la división binaria es similar a la decimal, excepto que cambiamos el decimal a binario, pero la idea general sigue siendo decimal.
  2. Estado en línea: Hay tres condiciones para nuestro estado en línea: 1. En la sala, 2. En línea, 3. Fuera de línea. Entonces podemos saber que solo necesitamos 2 personas para calcular el estado en línea del usuario, luego podemos considerar 0 como fuera de línea, 1 como en línea y 2 como en la sala. Convertido a binario está fuera de línea: 00, en línea: 01, en la habitación: 10. Como todavía tenemos pesos de usuario antes, necesitamos almacenar el estado en línea en el cuarto y quinto dígitos. En este momento, nuestro bit se convierte en el siguiente: uso el estado en línea como el estado de la habitación como se muestra:

Inserte la descripción de la imagen aquí
Lo convertimos a decimal: 42. Entonces la puntuación almacenada en redis también será 42.

  1. Género: dado que el género es una prioridad muy intermedia, puedo almacenarlo en el medio del bit entero. En este momento, podemos escribir:
    Inserte la descripción de la imagen aquí

Entonces, cuando obtenemos los datos nuevamente, si quiero sacar todos los datos masculinos en este momento, entonces puedo establecer mi rango de puntuación entre
0 ~ 1 << 16, entonces los datos en este rango son los datos masculinos, y Los mayores de 1 << 16 son datos de mujeres.
Entonces, ¿qué significa el símbolo de la operación de bits? Lo explicaré en detalle más adelante. Pero creo que puedo entender el símbolo de cambio a la izquierda ~

  1. Estado: en mi conocimiento, no debería haber nada más alto que la prioridad de estado, porque nuestro estado suele ser encendido, apagado, etc. Entonces, como solo tengo dos estados aquí, solo necesito usar 0 y 1 para representar diferentes estados. Por ejemplo, si utilizo 1 para indicar el estado desactivado y 0 para indicar el estado activado, entonces puedo escribirlo así:

Inserte la descripción de la imagen aquí

Luego, cuando obtengo datos, solo necesito establecer el intervalo de puntuación para los datos en el rango de 0 ~ 1 << 30, y luego se pueden recuperar todos los usuarios cuyo estado es encendido. Entonces, después de saber esto, ¿cómo calculamos la puntuación?

Puntaje de cálculo de división binaria

Primero, definamos una constante estática global:

/**
     * 用户在线状态bit长度
     */
    public static final int onlineStatusBits = 2;

    /**
     * 用户权重bit长度
     */
    public static final int WEIGHT_BITS= 4;

    /**
     * 用于保存用户性别 1女 0男
     */
    public static final int SCORE_WOMAN = 1 << 16;

    /**
     * 用户状态
     */
    public static final int SCORE_STATUS = 1 << 30;

Luego, al calcular la puntuación, tomando como ejemplo mi estado actual es el estado de la habitación y mi peso de usuario es 5, podemos escribir lo siguiente:

int score = (3 << WEIGHT_BITS) | 5;

El propósito de mover los WeightBits tres hacia la izquierda es dejar espacio para los bits bajos y dejar que nuestros pesos de usuario tengan un lugar. Luego, la puntuación se puede obtener mediante OR bit a bit. | El significado de este símbolo es: cuando se comparan dos valores numéricos en binario, los dígitos de los dos valores numéricos son 0 antes de que se convierta en 0, si uno de ellos es 1, es 1.
Tomo el código anterior como ejemplo:
3 << WeightBits se convierte a binario:
0011 0000
5 binario:
0000 0101
luego el resultado que calculamos por bit a bit OR es:
0011 0101
encontramos que los 4 bits superiores del resultado final son el valor de nuestro estado en línea, y el cuarto bit es Nuestro peso.
¿Y si queremos recuperar los datos?

Cómo obtener el valor correspondiente de la puntuación

De hecho, esto también es muy simple: usamos el resultado de 0011 0101 para calcular la distancia. Primero que nada, hablemos de cómo podemos sacar el número de dígitos.

(1 << bit) - 1 & score

Bien, en primer lugar, hablemos sobre el significado de & bit a bit y este símbolo. Entonces es así, se comparan los dos valores binarios, si ambos son 1, yo seré 1, de lo contrario será 0.
Entonces a través de esto, necesitamos calcular el peso del usuario es muy simple, solo necesitamos escribir así:

int weight = score & ((1 << WEIGHT_BITS) - 1);

1 Primero, lo dejamos después de que cuatro de su representación binaria se convierta en la siguiente:
0001 0000
En este punto ciertamente no podemos llevar a cabo tales operaciones y ciertamente estamos equivocados, entonces solo necesita -1, puede convertirse en
0000 1111
En este punto nuevamente Calculando la puntuación
0011 0101 a
través del bit a bit Y el resultado
0000 0101
también sacamos el valor de peso del usuario.

¿Y si queremos ir a otros valores elevados? Todavía usamos el ejemplo ahora, solo necesitamos escribir

int onlineStatus = (score >> WEIGHT_BITS) & ((1 << ONLINE_STATUS_BITS) - 1);

Mueva el puntaje a la derecha al peso, por ejemplo, 0011 0101 >> 4 dígitos
se convertirán en
0000 0011. En
este momento, a través de la operación AND bit a bit
0000 0011, el
resultado es el puntaje de nuestro valor de peso y otros algoritmos son los mismos.

Bueno, eso es todo por el artículo de hoy. Si te gusta, recuerda comentar, dar me gusta, reenviar y marcar como favorito ~

Supongo que te gusta

Origin blog.csdn.net/qq_39685066/article/details/109379747
Recomendado
Clasificación