(+351) 21 24 10006  ·  info@bconcepts.pt
Carnaxide, Lisboa

Cómo mantener contadores por usuario en Real-Time Analytics

João Barros 29 de August de 2026 4 min de lectura

Este tutorial muestra cómo mantener contadores por usuario en Real-Time Analytics, útil para métricas como eventos por sesión, límites por minuto o cuotas en tiempo real. Aprenderás a actualizar contadores incrementales, tratar duplicados simples y expirar contadores antiguos para controlar estado.

Requisitos previos

  • Cuenta y acceso a un servicio de Real-Time Analytics o streaming (por ejemplo, Azure Stream Analytics, Kusto/ADX o otro con soporte para stateful processing).
  • Fuente de eventos con campos: userId, eventId, eventTime.
  • Conocimientos básicos de SQL/KQL o del lenguaje de consulta del servicio usado.

Paso 1: Definir la granularidad y el estado que quieres mantener

Decide si el contador será por minuto, por hora, por sesión o acumulado. Esto determina la clave del estado y las reglas de expiración. Por ejemplo: contador por userId por minuto. La clave será (userId, minuteBucket).

Paso 2: Normalizar eventos y calcular el bucket de tiempo

Convierte eventTime a un bucket (p. ej.: minuto) para agrupar eventos en el mismo intervalo. Así se evitan problemas de zonas horarias y microsegundos.

// Exemplo KQL para transformar timestamp em bucket por minuto
Events
| extend minuteBucket = startofminute(eventTime)
| project userId, eventId, minuteBucket, eventTime

Paso 3: Deducción simple por eventId antes de actualizar el estado

Una deduplicación básica por eventId evita recuentos duplicados cuando eventos son reentregados. Mantén una pequeña caché de eventId por bucket (o usa una función dedupe del servicio).

// Exemplo conceptual: manter apenas o primeiro eventId por user/minute
Events
| extend minuteBucket = startofminute(eventTime)
| summarize firstEventTime = min(eventTime) by userId, minuteBucket, eventId
| summarize eventsCount = count() by userId, minuteBucket

Paso 4: Actualizar el estado con operación atómica (incremental)

Usa una operación atómica en el store de estado (Redis, Cosmos DB, Azure Table, state store do motor) para sumar el número de eventos por clave. Esto evita condiciones de carrera cuando múltiples workers procesan el mismo userId.

// Pseudocódigo conceptual para cada (userId, minuteBucket, delta)
stateKey = userId + ':' + minuteBucket
current = stateStore.get(stateKey) // pode ser 0 se não existir
newValue = current + delta
stateStore.set(stateKey, newValue, ttl=120s) // define TTL para expirar

Paso 5: Gestionar expiración y limpieza de estado

Define TTL (time-to-live) adecuado para los buckets: por ejemplo, mantener contadores durante 2-3 ventanas adicionales para permitir re-procesamiento. La expiración automática libera memoria y evita contadores permanentes para usuarios inactivos.

// Exemplo de TTL ao escrever em Redis (com comandos Redis simples)
// stateKey = "user:123:2026-08-29T12:34"
INCRBY stateKey 5
EXPIRE stateKey 180  // 180 segundos de TTL

Paso 6: Combinar contadores para informes (ejemplo por hora)

Para obtener métricas por hora combina los minuteBuckets dentro de la hora y suma los valores del state store. Puedes hacer esto en batch periódica o en una query que agregue las keys relevantes.

// Pseudocódigo para agregar 60 buckets de un user numa hora
hourBuckets = keysMatching("user:123:2026-08-29T12:*")
sum = 0
for k in hourBuckets:
    sum += get(k)
return sum

Verificar el resultado

Valida el comportamiento con estas pruebas: 1) Envía 10 eventos únicos para el mismo user en el mismo minuto y confirma que el contador sube a 10. 2) Reenvía un subconjunto de los mismos eventId y confirma que el contador no se duplica. 3) Espera hasta que el TTL expire y verifica que el estado se elimina. Usa logs y consultas al state store para confirmar los valores por key.

Conclusión

Manteniendo contadores por userId con buckets de tiempo, deduplicación por eventId, operaciones atómicas y TTL controlado, consigues métricas en tiempo real estables y eficientes. Próximos pasos: implementar sliding windows, manejar reordenamientos de eventos y usar un mecanismo de exactly-once cuando sea necesario. Consejo: empieza con TTL generoso y reduce a medida que las pruebas confirmen el comportamiento.