Gestión de registros de asistencia con Redis Bitmaps en Java

Los Bitmaps de Redis son estructuras de datos extremadamente eficientes para almacenar estados binarios (como "presente/ausente" o "activo/inactivo") asociados a una línea de tiempo o identificadores numéricos. En el entorno de desarrollo con Java, específicamente utilizando Spring Data Redis, podemos implementar sistemas de seguimiento de asistencia con un consumo de memoria mínimo.

1. Persistencia de datos en el Bitmap

Para registrar la actividad de un usuario, primero debemos definir una clave única que agrupe los datos, generalmente por usuario y periodo de tiempo (como mes y año). Luego, calculamos el desplazamiento (offset) basado en el día actual.

// Generación de la clave basada en el ID de usuario y el mes actual
LocalDate fechaHoy = LocalDate.now();
String patronMes = fechaHoy.format(DateTimeFormatter.ofPattern("yyyy:MM"));
String claveRedis = "usuario:registro:" + idUsuario + ":" + patronMes;

// El desplazamiento corresponde al día del mes (0 - 30)
long posicion = fechaHoy.getDayOfMonth() - 1;

// Guardar el estado en Redis (1 para asistencia)
redisTemplate.opsForValue().setBit(claveRedis, posicion, true);

2. Recuperación de secuencias de bits

Para obtener el historial de lo que va del mes, utilizamos el comando BITFIELD. Este comando nos permite extraer un segmento de bits y tratarlo como un número entero (Long), lo que facilita el procesamiento posterior en Java.

int diaActual = fechaHoy.getDayOfMonth();

// Obtenemos los bits desde el inicio del mes hasta el día de hoy
List<Long> resultadoBitfield = redisTemplate.opsForValue().bitField(
    claveRedis, 
    BitFieldSubCommands.create()
        .get(BitFieldSubCommands.BitFieldType.unsigned(diaActual))
        .valueAt(0)
);

3. Cálculo de racha de asistencia consecutiva

Un requerimiento común es determinar cuántos días seguidos ha cumplido un usuario con su registro hasta la fecha actual. Para lograr esto sin iterar sobre una base de datos relacional, procesamos el número decimal obtenido del Bitmap mediante operaciones de bits.

La lógica consiste en lo siguiente:

  • Realizar una operación AND entre el número y 1 para verificar si el último bit es 1.
  • Si es 1, incrementamos nuestro contador y desplazamos el número un bit hacia la derecha (oeprador >>>).
  • Si es 0, la racha se ha roto y detenemos el ciclo.
if (resultadoBitfield == null || resultadoBitfield.isEmpty()) {
    return 0;
}

// Representación decimal de la secuencia de bits
Long historialBinario = resultadoBitfield.get(0);
if (historialBinario == null || historialBinario == 0) {
    return 0;
}

int diasConsecutivos = 0;
while (true) {
    // Comprobar si el bit en la última posición es 1
    if ((historialBinario & 1) == 1) {
        diasConsecutivos++;
        // Desplazamiento a la derecha para evaluar el día anterior
        historialBinario >>>= 1;
    } else {
        // Se encontró un día sin registro
        break;
    }
}

return diasConsecutivos;

Este enfoque permite procesar meses enteros de actividad en cuestión de nanosegundos, ya que toda la lógica se reduce a manipulaciones matemáticas simples sobre un tipo de dato primitivo, evitando la sobrecarga de consultas complejas a disco.

Etiquetas: Redis java Spring Data Redis Bitmaps bitwise operations

Publicado el 8-12 19:42