The redis Hash structure stores commodity inventory, and the concurrency problem in the seckill scenario

In the flash sale scenario, using the Redis Hash structure to store commodity inventory may encounter concurrency issues. This is because a large number of users try to purchase the same product at the same time during the Lightning Deal, resulting in concurrent requests.

The following is one possible concurrency problem scenario:

  1. Suppose there are 100 commodity quantities (the key is "stock" and the value is 100) stored in the Hash structure of Redis.
  2. User A and user B query the inventory at the same time, and both find that the inventory is 100.
  3. User A submits an order and reduces the inventory quantity to 99.
  4. User B also submits an order, reducing the inventory quantity to 99 (actually expected to be 98).

It can be seen from the above scenario that under concurrent conditions, multiple users can query the same inventory quantity at the same time, and rush to buy goods at the same time according to the query results, resulting in the actual inventory reduction exceeding the actual inventory.

In order to solve the concurrency problem, the following solutions can be considered:

  1. Use Redis transactions (Transaction) to ensure atomic operations. Through commands such as MULTI, HGET, and HSET, the operations of querying inventory and reducing inventory are executed in one transaction. This ensures the atomicity of multiple commands and avoids concurrency issues.
  2. Use Redis's distributed lock (Distributed Lock) to ensure that only one user can perform inventory reduction operations at the same time. Before users rush to buy goods, acquire a distributed lock to ensure that only one user can enter the key code area, thereby ensuring the atomicity and thread safety of inventory operations.
  3. Use distributed systems or queues in business code to control inventory changes. By putting operations for physical inventory changes into a distributed system or queue, it is ensured that each operation occurs in order and that only one operation succeeds.

The above solutions can be selected and used in combination according to specific scenarios and requirements, so as to ensure that concurrency issues are handled in the seckill scenario.
The following is a simple example implemented in PHP, which demonstrates how to use the Redis Hash structure to deal with concurrency issues in the seckill scenario.

<?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();

?>

In the above sample code, first we connect to Redis and define a seckill function to process seckill business logic. In the seckill function, we first obtain the commodity inventory, and if the inventory is greater than 0, perform seckill operation, that is, reduce the inventory by 1, and update the inventory value in Redis. At the same time, other operations such as generating orders can also be performed. If the stock is sold out, output the corresponding prompt message.

Then, we use the pcntl_fork function to create a child process through the concurrent simulation part, and call the seckill function in the child process to perform seckill. You can modify the $seckillNum parameter as needed to set the number of people snapping up at the same time.

Finally, the parent process waits for the child process to complete and closes the Redis connection.

Note: The above example is a simplified demonstration code, and more details and security issues need to be considered in actual applications, such as interface anti-brush, overselling issues, etc.

Guess you like

Origin blog.csdn.net/qq_27487739/article/details/131730146