O comando EXINCRBY do TairString impõe limites superiores e inferiores rígidos de forma atômica, sem necessidade de scripts Lua em casos simples. Esse recurso é ideal para rastrear estoque em vendas relâmpago e limitar taxas, cenários em que ultrapassar um limiar gera consequências reais.
Como funciona
Os comandos EXINCRBY e EXINCRBYFLOAT estendem os comandos nativos INCRBY e INCRBYFLOAT do Redis com opções adicionais, incluindo MIN e MAX:
|
Opção |
Descrição |
|
|
Rejeita a operação se o resultado ficar abaixo deste valor |
|
|
Rejeita a operação se o resultado exceder este valor |
|
|
Defina a expiração em segundos |
|
|
Defina o valor apenas se a chave não existir |
|
|
Verifica a versão para bloqueio otimista |
|
|
Preserva o TTL existente |
Ao violar um limite, o EXINCRBY retorna "increment or decrement would overflow" em vez de atualizar a chave. Trate essa resposta como sinal para interromper a aceitação da requisição, sem necessidade de verificação secundária.
Cada chamada ao EXINCRBY é atômica. Não há intervalo entre leitura e escrita em que duas requisições simultâneas possam visualizar o mesmo valor restante.
O TairString oferece suporte a todos os recursos nativos de String do Redis, exceto operações de bits.
Para obter a referência completa dos comandos, consulte Comandos do TairString.
Quando usar contadores limitados
Use EXINCRBY com MIN/MAX quando for necessário um limiar rígido intransponível:
|
Cenário |
Abordagem |
Adequação dos contadores limitados |
|
Estoque de venda relâmpago |
Decrementar com |
O estoque nunca fica negativo; evita vendas excessivas |
|
Limite de requisições simultâneas |
Incrementar com |
As requisições ativas nunca excedem N |
|
Limitação de tentativas de login |
Incrementar com |
O limite é redefinido após a expiração da janela |
|
Limitação de taxa de alteração de senha |
Incrementar com |
Impede credential stuffing no nível do contador |
Comparação com INCRBY nativo do Redis e Lua: Strings nativas exigem um script Lua para ler, comparar e atualizar condicionalmente em uma única etapa atômica. O EXINCRBY executa isso em um único comando, reduzindo a complexidade do código e as idas e vindas à rede. Use strings nativas com Lua caso precise de lógica condicional mais complexa além de um limiar fixo de mínimo/máximo.
Controle de estoque em vendas relâmpago
Para evitar vendas excessivas, defina a contagem inicial de estoque como valor do TairString e decremente com MIN 0. Assim que o estoque chegar a zero, o EXINCRBY rejeitará automaticamente novos decrementos.
if(EXINCRBY(key_iphone, -1, MIN:0) == "would overflow")
run_out();
Limitação de taxa e throttling
Use MAX para limitar o contador a um teto superior. O exemplo a seguir restringe as requisições simultâneas a 1.000:
if(EXINCRBY(rate_limitor, 1, MAX:1000) == "would overflow")
traffic_control();
Esse padrão aplica-se a qualquer cenário com limiar numérico: consultas por segundo (QPS), conexões simultâneas, tentativas de login ou frequência de alteração de senha.
Exemplo em Java: limitador de requisições simultâneas
O método tryAcquire a seguir é thread-safe. Ele incrementa o contador dentro de uma janela de expiração e retorna false ao atingir o limite superior.
/**
* Attempts to acquire a slot within the rate limit window.
*
* @param key The rate limit key
* @param upperBound The maximum allowed count
* @param interval The time window in seconds
* @return true if the slot was acquired; false if the limit is reached
*/
public static boolean tryAcquire(String key, int upperBound, int interval) {
try (Jedis jedis = jedisPool.getResource()) {
jedis.eval("if redis.call('exists', KEYS[1]) == 1 "
+ "then return redis.call('EXINCRBY', KEYS[1], '1', 'MAX', ARGV[1], 'KEEPTTL') "
+ "else return redis.call('EXSET', KEYS[1], 0, 'EX', ARGV[2]) end",
Arrays.asList(key), Arrays.asList(String.valueOf(upperBound), String.valueOf(interval)));
return true;
} catch (Exception e) {
if (e.getMessage().contains("increment or decrement would overflow")) {
return false;
}
e.printStackTrace();
}
return false;
}
O script Lua combina duas operações atomicamente:
Se a chave existir: incrementa com
EXINCRBY, aplicaMAXe preserva o TTL existente comKEEPTTL.Se a chave não existir: inicializa-a com
0viaEXSETe defina a janela de expiração comEX.
Tratamento de falhas em produção: O método tryAcquire captura o overflow como sinal esperado de fluxo de controle. Para outras exceções — como falha de conexão com o Redis — o método registra o erro e retorna false, adotando a estratégia fail closed (bloqueia requisições). Decida se sua aplicação deve adotar fail open (permitir requisições) ou fail closed (bloquear requisições) quando o TairString estiver indisponível e atualize o manipulador de exceções adequadamente.
Próximos passos
Comandos do TairString — referência completa para
EXINCRBY,EXINCRBYFLOAT,EXSETe todas as opções suportadas