Comandos Fundamentales para Transacciones
Inicio de Bloque Transaccional: MULTI
El comando MULTI inicia un bloque transaccional, encolando operacoines subsiguientes sin ejecutarlas inmediatamente:
MULTI
SET producto:existencia 50
SET pedido:usuario123 estado "pendiente"
Ejecución Transaccional: EXEC
EXEC ejecuta todas las operaciones encoladas atómicamente:
EXEC
Cancelación de Transacciones: DISCARD
Descarta todas las operaciones pendientes en el bloque actual:
MULTI
SET item:A 100
SET item:B 200
DISCARD
Monitorización de Claves: WATCH
Bloquea la ejecución si las claves vigiladas son modificadas externamente:
WATCH saldo:cliente
MULTI
SET saldo:cliente 500
EXEC
Escnearios Prácticos de Aplicación
Sistema de Inventarios
Actualización atómica de existencias y registro de ventas:
WATCH inventario:zapatos
MULTI
DECR inventario:zapatos
HSET venta:dia123 producto "zapatos" cantidad 1
EXEC
Transferencias Bancarias
Movimientos monetarios atómicos entre cuentas:
WATCH cuenta:origen cuenta:destino
MULTI
DECRBY cuenta:origen 300
INCRBY cuenta:destino 300
EXEC
Consideraciones Clave
Manejo de Errores
Los errores sintácticos solo se detectan durante EXEC, deteniendo toda la transacción.
Ausencia de Rollback Automático
Comandos fallidos no revierten operaciones exitosas previas en la misma transacción.
Impacto en Rendimiento
Ejecución secuencial en bloques grandes puede generar cuellos de botella.
Implementaciones en Go
Ejemplo de Sistema de Inventarios
package main
import (
"context"
"fmt"
"github.com/go-redis/redis/v8"
)
var ctx = context.Background()
func main() {
cliente := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
})
err := cliente.Watch(ctx, func(tx *redis.Tx) error {
if tx.Get(ctx, "inventario:zapatos").Err() != nil {
return err
}
operaciones := tx.TxPipeline()
operaciones.Decr(ctx, "inventario:zapatos")
operaciones.HSet(ctx, "venta:dia123", "producto", "zapatos", "cantidad", 1)
_, err := operaciones.Exec(ctx)
return err
}, "inventario:zapatos")
if err != nil {
fmt.Println("Error en transacción:", err)
}
}
Ejemplo de Transferencia Bancaria
package main
import (
"context"
"fmt"
"github.com/go-redis/redis/v8"
)
var ctx = context.Background()
func main() {
conexion := redis.NewClient(&redis.Options{
Addr: "servidor:6379",
})
err := conexion.Watch(ctx, func(tx *redis.Tx) error {
if tx.Get(ctx, "cuenta:origen").Err() != nil || tx.Get(ctx, "cuenta:destino").Err() != nil {
return err
}
pipeline := tx.TxPipeline()
pipeline.DecrBy(ctx, "cuenta:origen", 300)
pipeline.IncrBy(ctx, "cuenta:destino", 300)
_, err := pipeline.Exec(ctx)
return err
}, "cuenta:origen", "cuenta:destino")
if err != nil {
fmt.Println("Fallo en transferencia:", err)
}
}