A estrutura redis Hash armazena estoque de commodities e o problema de simultaneidade no cenário seckill

No cenário de venda rápida, usar a estrutura Redis Hash para armazenar o estoque de mercadorias pode encontrar problemas de simultaneidade. Isso ocorre porque um grande número de usuários tenta comprar o mesmo produto ao mesmo tempo durante o Lightning Deal, resultando em solicitações simultâneas.

O seguinte é um possível cenário de problema de simultaneidade:

  1. Suponha que existam 100 quantidades de mercadorias (a chave é "estoque" e o valor é 100) armazenadas na estrutura Hash do Redis.
  2. O usuário A e o usuário B consultam o inventário ao mesmo tempo e ambos descobrem que o inventário é 100.
  3. O usuário A envia um pedido e reduz a quantidade de estoque para 99.
  4. O usuário B também envia um pedido, reduzindo a quantidade de estoque para 99 (na verdade, espera-se que seja 98).

Pode-se ver no cenário acima que, em condições simultâneas, vários usuários podem consultar a mesma quantidade de estoque ao mesmo tempo e correr para comprar mercadorias ao mesmo tempo de acordo com os resultados da consulta, resultando na redução real do estoque excedendo o real inventário.

Para resolver o problema de concorrência, as seguintes soluções podem ser consideradas:

  1. Use transações Redis (Transação) para garantir operações atômicas. Por meio de comandos como MULTI, HGET e HSET, as operações de consulta de estoque e redução de estoque são executadas em uma única transação. Isso garante a atomicidade de vários comandos e evita problemas de simultaneidade.
  2. Use o bloqueio distribuído do Redis (Distributed Lock) para garantir que apenas um usuário possa realizar operações de redução de estoque ao mesmo tempo. Antes que os usuários corram para comprar mercadorias, adquira um bloqueio distribuído para garantir que apenas um usuário possa entrar na área do código-chave, garantindo assim a atomicidade e a segurança do thread das operações de estoque.
  3. Use sistemas distribuídos ou filas no código de negócios para controlar as mudanças de estoque. Ao colocar operações para alterações de inventário físico em um sistema distribuído ou fila, é garantido que cada operação ocorra em ordem e que apenas uma operação seja bem-sucedida.

As soluções acima podem ser selecionadas e usadas em combinação de acordo com cenários e requisitos específicos, de modo a garantir que os problemas de simultaneidade sejam tratados no cenário de segurança.
A seguir, um exemplo simples implementado em PHP, que demonstra como usar a estrutura Redis Hash para lidar com problemas de simultaneidade no cenário seckill.

<?php

// 假设秒杀商品的ID为1001,库存存储在"stock"键下
$productId = 1001;

// 连接Redis
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);

// 秒杀函数
function seckill($productId) {
    
    
    global $redis;

    // 获取商品库存
    $stock = $redis->hget('stock', $productId);

    if ($stock > 0) {
    
    
        // 有库存,执行秒杀逻辑
        $stock -= 1;

        // 更新库存
        $redis->hset('stock', $productId, $stock);

        // 执行生成订单等其他逻辑
        echo '成功抢购商品'.$productId.PHP_EOL;
    } else {
    
    
        // 库存已售罄
        echo '商品'.$productId.'已售罄'.PHP_EOL;
    }
}

// 并发模拟
$seckillNum = 5; // 模拟同时抢购人数
$pid = pcntl_fork();

if ($pid === -1) {
    
    
    echo 'Fork进程失败';
    exit(1);
} else if ($pid === 0) {
    
    
    // 子进程执行秒杀
    for ($i = 0; $i < $seckillNum; $i++) {
    
    
        seckill($productId);
    }
} else {
    
    
    // 父进程等待子进程执行完毕
    pcntl_wait($status);
}

// 关闭Redis连接
$redis->close();

?>

No código de exemplo acima, primeiro nos conectamos ao Redis e definimos uma função seckill para processar a lógica de negócios seckill. Na função seckill, primeiro obtemos o estoque de commodities e, se o estoque for maior que 0, executamos a operação seckill, ou seja, reduzimos o estoque em 1 e atualizamos o valor do estoque no Redis. Ao mesmo tempo, outras operações como geração de pedidos também podem ser realizadas. Se o estoque estiver esgotado, emita a mensagem de prompt correspondente.

Em seguida, usamos a função pcntl_fork para criar um processo filho por meio da parte de simulação simultânea e chamamos a função seckill no processo filho para executar o seckill. Você pode modificar o parâmetro $seckillNum conforme necessário para definir o número de pessoas que se encaixam ao mesmo tempo.

Por fim, o processo pai aguarda a conclusão do processo filho e fecha a conexão Redis.

Nota: O exemplo acima é um código de demonstração simplificado, e mais detalhes e problemas de segurança precisam ser considerados em aplicativos reais, como interface anti-brush, problemas de overselling, etc.

Acho que você gosta

Origin blog.csdn.net/qq_27487739/article/details/131730146
Recomendado
Clasificación