Construye Sistemas Reactivos con Clustron Watch
La mayoría de los sistemas distribuidos no empiezan siendo complicados.
Empiezan con algo sencillo: un bucle.
Escribes un pequeño trabajador que comprueba si hay trabajo:
while (true)
{
var job = await client.GetAsync<Job>("jobs:next");
if (job.IsSuccess)
{
await ProcessAsync(job.Value);
}
await Task.Delay(1000);
}
En esta etapa, todo parece razonable. La lógica es clara, el sistema se comporta de forma predecible y la carga cognitiva es muy baja.
Pero a medida que el sistema crece, este patrón se convierte silenciosamente en una de las partes más costosas de tu arquitectura.
El coste oculto del sondeo en los sistemas distribuidos
El sondeo introduce una ineficiencia fundamental: estás preguntando repetidamente al sistema por cambios que normalmente no se han producido.
A medida que escalas:
- Varias instancias comienzan a sondear los mismos datos
- Cada instancia realiza lecturas repetidas, la mayoría de las cuales no devuelven información útil
- Introduces latencia artificial: los cambios solo se detectan en el siguiente ciclo de sondeo
- El sistema empieza a consumir recursos simplemente para confirmar que nada ha cambiado
Esto conduce a un sistema que es técnicamente correcto, pero operativamente ineficiente.
Y lo que es más importante, el sondeo te obliga a hacer concesiones que no deberías tener que hacer:
- Sondear con frecuencia → mayor coste, menor latencia
- Sondear con menos frecuencia → menor coste, mayor latencia
No hay una respuesta correcta, solo un compromiso.
Un modelo diferente: reaccionar en lugar de preguntar
La alternativa no es solo una optimización: es una forma diferente de pensar en los sistemas.
En lugar de preguntar:
"¿Ha cambiado algo?"
Diseñas tu sistema para que responda a:
"Algo acaba de cambiar."
Este es el cambio de un modelo basado en extracción (pull) a un modelo basado en inserción (push).
En Clustron, esto se implementa mediante Watch.

Presentando Watch: un flujo de cambios de estado
Clustron Watch te permite suscribirte a los cambios del sistema y recibir eventos a medida que ocurren.
En esencia, Watch convierte tus datos en un flujo continuo de actualizaciones.
Observar una sola clave
var (subscription, initialRecord) = await client.Watch.WatchKeyAsync(
"order:1001",
new WatchOptions { IncludeInitialSnapshot = true },
ev =>
{
Console.WriteLine($"{ev.EventType} → {ev.Key} = {ev.Value}");
});
Esto hace dos cosas importantes:
- Te proporciona el estado actual (
initialRecord) - Te suscribe a todos los cambios futuros
Esta combinación es fundamental. Sin ella, tendrías que obtener manualmente el valor actual y luego suscribirte, lo que introduce condiciones de carrera.
Instantánea + streaming: una garantía de corrección
Uno de los aspectos sutiles pero esenciales de Watch es la capacidad de incluir una instantánea inicial.
Cuando IncludeInitialSnapshot está habilitado:
- Recibes el valor actual en el momento de la suscripción
- Luego recibes todas las actualizaciones posteriores en orden
Esto garantiza que:
- No pierdas el estado existente
- No pierdas los cambios futuros
- No necesites lógica de sincronización adicional
En otras palabras, Watch proporciona una vista completa y consistente de la evolución del estado.
Observar colecciones: más allá de las claves individuales
Si bien observar una sola clave es útil, la mayoría de los sistemas reales operan sobre grupos de datos relacionados.
Clustron admite esto mediante la observación basada en prefijos:
var subscription = await client.Watch.WatchPrefixAsync(
"jobs:",
new WatchOptions { IncludeInitialSnapshot = false },
ev =>
{
Console.WriteLine($"Job update: {ev.Key}");
});
Esto te permite observar todos los cambios dentro de un grupo lógico.
Desde una perspectiva arquitectónica, aquí es donde Watch se vuelve significativamente más potente:
- Ya no reaccionas a valores individuales
- Reaccionas a transiciones de estado de todo el sistema
Comprender el modelo de eventos
Cada cambio en el sistema produce un WatchEvent.
Un evento típico contiene:
- La clave que cambió
- El tipo de cambio (
PutoDelete) - El nuevo valor (si corresponde)
- Una revisión que representa la versión del cambio
Esta revisión es particularmente importante. Proporciona un orden y te permite razonar sobre la secuencia de eventos en un sistema distribuido.
En efecto, Watch te proporciona un registro de transiciones de estado, entregado en tiempo real.
Qué permite esto en la práctica
Una vez que adoptas este modelo, varios problemas comunes se simplifican.
Procesamiento de trabajos
En lugar de sondear en busca de nuevo trabajo, los trabajadores reaccionan de inmediato cuando se crean o actualizan trabajos.
Esto elimina los ciclos inactivos y reduce la latencia.
Invalidación de caché
En lugar de depender del TTL o de la actualización periódica, las cachés pueden actualizarse a sí mismas en respuesta a cambios reales.
Esto mejora tanto la frescura como la eficiencia.
Coordinación distribuida
Los sistemas que dependen de un estado compartido —como la elección de líder o la propiedad de concesiones— se benefician significativamente de las actualizaciones en tiempo real.
Los cambios se propagan al instante, lo que permite una coordinación más rápida y fiable.
Presencia y supervisión
El seguimiento de los componentes activos se vuelve trivial:
- Cuando aparece un nodo → recibes un evento
- Cuando desaparece un nodo → recibes un evento
Sin sondeo, sin conjeturas.
Consideraciones operativas
Watch está diseñado para cargas de trabajo de larga duración y orientadas a eventos.
Algunas consideraciones importantes:
Mantén los controladores ligeros
Tu controlador de eventos no debe realizar trabajo pesado directamente.
En su lugar:
- Procesa rápidamente
- Delega las tareas más pesadas a trabajadores en segundo plano
Gestiona el ciclo de vida de la suscripción
Detén siempre las suscripciones cuando ya no sean necesarias:
await subscription.StopAsync();
Esto garantiza que los recursos se liberen de forma limpia.
Comprende el alcance
- Observar una clave → solo esa clave produce eventos
- Observar un prefijo → solo las claves coincidentes producen eventos
Los eventos están delimitados y aislados, lo que evita interferencias no deseadas entre componentes.
De los bucles de sondeo a los sistemas reactivos
El cambio del sondeo a la observación no se trata solo de rendimiento.
Cambia la estructura de tu aplicación.
Los sistemas de sondeo se construyen en torno a:
Loop → Check → Wait → Repeat
Los sistemas reactivos se construyen en torno a:
Event → Handler → Action
Esto da lugar a sistemas que son:
- Más receptivos
- Más eficientes
- Más fáciles de razonar
Reflexiones finales
El sondeo suele ser la forma más sencilla de empezar y, en sistemas pequeños, funciona lo suficientemente bien.
Pero a medida que los sistemas crecen, el coste del sondeo se vuelve cada vez más difícil de justificar.
Clustron Watch ofrece un enfoque diferente: uno en el que tu sistema reacciona al cambio en lugar de buscarlo.
Stop asking your system if something changed.
Let it tell you when it does.
Primeros pasos
Prueba una observación sencilla:
await client.Watch.WatchPrefixAsync("orders:", null, ev =>
{
Console.WriteLine($"{ev.Key} updated");
});
A partir de ahí, empieza a eliminar los bucles de sondeo, uno por uno.
Rápidamente descubrirás que tu sistema se vuelve no solo más rápido, sino fundamentalmente más simple.