首页> 文章> 详情

Spring Boot Redis 秒杀实现

教程分享 > Java教程 (3619) 2024-04-17 12:31:28

简述

本文主要通过一个简单的例子模拟实现秒杀情景,其中主要使用Redis事物进行实现spring boot为提供方便的环境。

首先导入redis依赖

pom.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.leftso.demo</groupId>
    <artifactId>demo-redis-seckill</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo-redis-seckill</name>
    <description>Redis 实现产品秒杀</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>3.0.1</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

Redispool配置

配置redis的连接池,这个根据自己需求改。这里测试用。

package com.leftso.demo.demoredisseckill;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

@Configuration
public class JedisConfig {

    @Bean
    public JedisPool jedisPool(){
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        // 设置配置
        jedisPoolConfig.setMaxTotal(1024);
        jedisPoolConfig.setMaxIdle(100);
        jedisPoolConfig.setMaxWaitMillis(100);
        jedisPoolConfig.setTestOnBorrow(false);//jedis 第一次启动时,会报错
        jedisPoolConfig.setTestOnReturn(true);
        JedisPool pool=new JedisPool(jedisPoolConfig,"127.0.0.1",6379);
        return pool;
    }
}

写一个秒杀的业务处理实现

package com.leftso.demo.demoredisseckill.service;


import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.Transaction;

import java.util.List;

public class Seckill implements Runnable {
    private JedisPool jedisPool;
    private String userName;
    private String productKey;

    public Seckill(JedisPool jedisPool, String userName, String productKey) {
        this.jedisPool = jedisPool;
        this.userName = userName;
        this.productKey = productKey;
    }


    @Override
    public void run() {
        Jedis jedis=jedisPool.getResource();
        try {
            jedis.watch(productKey);
            String val=jedis.get(productKey);
            int valInt=Integer.valueOf(val);
            if (valInt>=1){
                Transaction tx=jedis.multi();
                tx.incrBy(productKey,-1);//原子操作
                List<Object> list=tx.exec();
                if (list==null||list.isEmpty()){
                    System.out.println("用户:"+userName+" 抢购失败。");
                    this.run();//再抢
                }else{
                    System.out.println("用户:"+userName+ " 抢购成功!!!");
//                    jedis.setnx(productKey,)
                    jedis.rpush(productKey+"user",userName);//成功用户添加入队列
                }
            }else{
                System.out.println("商品已抢购完毕-------");
            }

        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

最后模拟访问

package com.leftso.demo.demoredisseckill;

import com.leftso.demo.demoredisseckill.service.Seckill;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import redis.clients.jedis.JedisPool;

import java.util.ArrayList;
import java.util.List;

@RunWith(SpringRunner.class)
@SpringBootTest
public class RedisSeckillTest {
    private final static Logger logger = LoggerFactory.getLogger(RedisSeckillTest.class);

    @Autowired
    JedisPool jedisPool;

    String productKey="SSSSSSKEY";
    int productNum=10;

    @Before
    public void before(){
        jedisPool.getResource().set(productKey,10+"");//设置产品默认库存数量
        while (jedisPool.getResource().lpop(productKey+"user")!=null){

        }//清空秒杀成功人用户列表
        //end
    }

    @After
    public void after(){
        String num=jedisPool.getResource().get(productKey);
        System.out.println("剩余库存:"+num);
    }

    @Test
    public void contextLoads() {
        try {
            for (int i = 0; i < 100; i++) {
                //每个用户件数
                Thread t = new Thread(new Seckill(jedisPool,"用户"+i,productKey));
                t.start();
            }

            long size=jedisPool.getResource().llen(productKey+"user");
            while (true){
                if (size==productNum){
                    break;
                }else{
                    size=jedisPool.getResource().llen(productKey+"user");
                }
            }
            List<String> successUsers=new ArrayList<>();
            String  user=jedisPool.getResource().lpop(productKey+"user");
            while (user!=null){
                successUsers.add(user);
                user=jedisPool.getResource().lpop(productKey+"user");
            }


            System.out.println("活动结束>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>活动结束");
            System.out.println("获奖名单:"+successUsers);
            Thread.currentThread().sleep(2000);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

执行单元测试,查看结果:
..............................
商品已抢购完毕-------
商品已抢购完毕-------
商品已抢购完毕-------
商品已抢购完毕-------
商品已抢购完毕-------
商品已抢购完毕-------
商品已抢购完毕-------
商品已抢购完毕-------
商品已抢购完毕-------
商品已抢购完毕-------
商品已抢购完毕-------
商品已抢购完毕-------
商品已抢购完毕-------
商品已抢购完毕-------
商品已抢购完毕-------
商品已抢购完毕-------
活动结束>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>活动结束
获奖名单:[用户66, 用户2, 用户8, 用户10, 用户56, 用户78, 用户33, 用户58, 用户16, 用户87]
剩余库存:0

Process finished with exit code 0


您有任何想法欢迎评论区留言讨论,谢谢
 
https://www.leftso.com/article/615.html

相关文章
简述本文主要通过一个简单的例子模拟实现秒杀情景,其中主要使用Redis事物进行实现spring boot为提供方便的环境
前言继续上一篇Spring Boot Redis 秒杀实现 的一个修改版本,主要实现用ab工具进行网页正式访问的一个版本,其主要目的还是介绍Redis实现秒杀活动的一种方式
spring boot 1.5整合redis实现spring的缓存框架,spring boot,redis
Spring Boot 2.0 Redis整合,通过spring boot 2.0整合Redis作为spring缓存框架的实现。
redis 命令查看使用情况redis info命令详解,redis查看内存使用情况。redis info命令的详细解释
spring data redis设置缓存的过期时间,spring data redis更新缓存的过期时间
Redis 删除/清除数据​​​​​​​1.访问redis根目录    cd  /usr/local/redis-2.8.192.登录redis:redis-cli -h 127.0.0.1 -...
Redis 禁用持久化配置
redis在window系统上的下载安装使用说明
Java连接redis启动报错Error redis clients jedis HostAndPort cant resolve localhost address
Java编程之spring boot shiro redis整合基于角色和权限的安全管理,Java编程,spring boot,shiro,权限控制
今天遇到Redis “MISCONF Redis is configured to save RDB snapshots, but is currently not able to persis...
简述在本博客中,我们将会创建一个reids的消息队列,Redis可以被当成消息队列使用
spring boot 入门之整合spring session实现session共享。一直以来Java编程中web项目中的session共享问题都是一个很难解决的问题。接下来将讲解通过sprin...
centos6 yum安装redis3.29,centos6 源码安装redis以及常用配置