Home  >  Article  >  Database  >  Let's talk about the issue of realizing flash sales with Redis

Let's talk about the issue of realizing flash sales with Redis

WBOY
WBOYforward
2022-05-27 11:40:343257browse

This article brings you relevant knowledge about Redis, which mainly introduces the relevant content about realizing flash sales, including flash sale logic, existing link timeouts, overselling and inventory legacy Let’s take a look at the problem below. I hope it will be helpful to everyone.

Let's talk about the issue of realizing flash sales with Redis

Recommended learning: Redis video tutorial

1. Flash sale logic

Second sale : Solve the transaction operations of counters and personnel records

    ##1. Judgment that uid and proid are not empty
  1. 2. Connect to redis
  2. 3. Splicing key
    • Inventory key
    • Successful flash sale user key
  3. 4. Get the inventory. If the inventory is null, the flash sale has not started yet
  4. 5. Determine whether the user repeats the flash sale operation
  5. 6. Determine the quantity of the product. If the inventory quantity is less than 1, the flash sale ends
  6. 7. Flash sale process
    • Inventory-1
    • Add users who have successfully flash killed to the list
2. Problems

2.1. Connection timeout

Reason: Due to a large number of Creating a connection consumes a lot of performance, and sometimes the connection is not obtained in time, and the connection times out.

2.2. Overselling

occurs under concurrent conditions, that is, when the output is out of stock (flash sale) After the end), there are still goods sold, resulting in a negative inventory quantity.


Lets talk about the issue of realizing flash sales with Redis

2.3. Inventory legacy

After using optimistic lock to solve problem 2, problem 3 appears

If the inventory quantity is relatively more concurrent, due to the use of optimism Lock, after the first user succeeds in the flash sale, the version number of the inventory key will be modified. Other users who grab it will be unable to continue purchasing due to different version numbers, and there will be inventory legacy issues

3. Solution

3.1. Connection timeout

Use connection pool, the tool class is as follows:

public class JedisPoolUtil {
	private static volatile JedisPool jedisPool = null;
	private JedisPoolUtil() {
	}
	public static JedisPool getJedisPoolInstance() {
		if (null == jedisPool) {
			synchronized (JedisPoolUtil.class) {
				if (null == jedisPool) {
					JedisPoolConfig poolConfig = new JedisPoolConfig();
					poolConfig.setMaxTotal(200);
					poolConfig.setMaxIdle(32);
					poolConfig.setMaxWaitMillis(100 * 1000);
					poolConfig.setBlockWhenExhausted(true);
					poolConfig.setTestOnBorrow(true);
					jedisPool = new JedisPool(poolConfig, "127.0.0.1", 6379, 60000);
				}
			}
		}
		return jedisPool;
	}}//使用JedisPool jedisPoolInstance = JedisPoolUtil.getJedisPoolInstance();Jedis jedis = jedisPoolInstance.getResource();
springBoot version (pom.xml introduction, application.yml configuration, and then inject the object)

<dependency>
    <groupid>org.springframework.boot</groupid>
    <artifactid>spring-boot-starter-data-redis</artifactid></dependency><dependency>
    <groupid>redis.clients</groupid>
    <artifactid>jedis</artifactid>
    <version>3.2.0</version></dependency>
spring:
  redis:
    host: 127.0.0.1    port: 6379
    database: 0
    timeout: 1800000
    lettuce:
      pool:
        max-active: 20
        max-wait: -1
        max-idle: 5
        min-idle: 0
    @Autowired
    private RedisTemplate redisTemplate;
3.2. Oversold problem

Use Redis transaction, optimistic lock watch

//监视库存
jedis.watch(kcKey);//中间代码忽略

//7 秒杀过程
//使用事务
Transaction multi = jedis.multi();//组队操作
multi.decr(kcKey);multi.sadd(userKey,uid);//执行
List<object> results = multi.exec();if(results == null || results.size()==0) {
    System.out.println("秒杀失败了....");
    jedis.close();
    return false;}</object>
3.3. Inventory legacy problems caused by optimistic lock

Use Lua embedded scripting language

    Write complex or multi-step Redis operations as a script and submit it to Redis for execution at one time to reduce the number of repeated connections to redis. Improve performance.
  1. LUA script is similar to a redis transaction. It has a certain degree of atomicity and will not be queued by other commands. It can complete redis transactional operations.
  2. LUA script function is only available in Redis 2.6 or above. You can use
  3. to use lua scripts to eliminate users and solve the overselling problem.
  4. After version 2.6 of redis, the contention problem is solved through
  5. lua script. In fact, redis uses its single-threaded feature to solve the multi-task concurrency problem using a task queue.
  6. local userid=KEYS[1];				//1、2行定义两个变量,					
    local prodid=KEYS[2];
    local qtkey="sk:"..prodid..":qt";	//3,4行定义拼接key
    local usersKey="sk:"..prodid..":usr";
    local userExists=redis.call("sismember",usersKey,userid); //5-8,判断用户是否存在,不存在return 2
    if tonumber(userExists)==1 then
        return2;
    end
    local num=redis.call("get",qtkey);	//9-11,判断商品是否存在
    if tonumber(num)
The complete code is as follows:

// 定义两段Lua脚本(使用Lua脚本可以解决乐观锁带来的库存遗留问题)
	static String secKillScript =
			"local userid=KEYS[1];\r\n" +
					"local prodid=KEYS[2];\r\n" +
					"local qtkey='sk:'..prodid..\":qt\";\r\n" +
					"local usersKey='sk:'..prodid..\":usr\";\r\n" +
					"local userExists=redis.call(\"sismember\",usersKey,userid);\r\n" +
					"if tonumber(userExists)==1 then \r\n" +
					"   return 2;\r\n" +
					"end\r\n" +
					"local num= redis.call(\"get\" ,qtkey);\r\n" +
					"if tonumber(num)Recommended learning: <p>Redis video tutorial<a href="https://www.php.cn/course/list/54.html" target="_blank"></a></p>

The above is the detailed content of Let's talk about the issue of realizing flash sales with Redis. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:csdn.net. If there is any infringement, please contact admin@php.cn delete