Redis实现商品秒杀

文章目录

  • 为什么使用Redis?
  • SpringDataRedis
  • 怎么实现?
  • 具体实现
    • 搭建开发环境
    • SpringBoot项目的启动类
    • Dao层
    • Service层
    • 测试功能

商品秒杀是一个非常常见的场景,今天我们就使用Redis来实现商品秒杀功能。

为什么使用Redis?

  • Redis是一款非关系数据库,数据存储在内存中,存取数据速度非常快!
  • Redis是单线程的,即使在同一时间有多条命令操作数据库,这些命令依然只能排队等候。

SpringDataRedis

SpringDataRedis是一款Java语言实现的Redis数据库的操作API,它是SpringData系列的框架之一,专门用于操作Redis,而且可以和SpringBoot进行无缝整合。

怎么实现?

Redis可以存储五种数据结构,我们使用列表数据来实现商品秒杀功能。

  • 我们将商品信息作为列表结构的key值,给列表push商品库存个数的value。
  • 当商品秒杀的时候,我们使用pop命令从列表中取出数据即可。

具体实现

搭建开发环境


<parent>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-parentartifactId>
    <version>2.0.4.RELEASEversion>
parent>

<dependencies>
    
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-testartifactId>
        <scope>testscope>
    dependency>
    
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-data-redisartifactId>
    dependency>
    
    <dependency>
        <groupId>org.projectlombokgroupId>
        <artifactId>lombokartifactId>
    dependency>
dependencies>

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

SpringBoot项目的启动类

@SpringBootApplication
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class);
    }
}

Dao层

  • Dao层接口
public interface CommodityDao {
    /**
     * 将商品加入库存
     * @param key
     * @param value
     */
    void addStock(String key,String value);

    /**
     * 秒杀商品
     * @param key
     * @return
     */
    String spike(String key);
}
  • Dao层实现
@Repository
public class CommodityDaoImpl implements CommodityDao {

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public void addStock(String key,String value) {
        redisTemplate.boundListOps(key).leftPush(value);
    }

    @Override
    public String spike(String key) {
        return (String) redisTemplate.boundListOps(key).leftPop();
    }
}

Service层

  • Service层接口
public interface CommodityService {
    /**
     * 将商品加入库存
     * @param stock
     */
    void addStock(int stock);

    /**
     * 秒杀商品
     * @return
     */
    String spike() ;
}
  • Service层实现
@Service
public class CommodityServiceImpl implements CommodityService {

    @Autowired
    private CommodityDao commodityDao;

    private final static String KEY = "commodity";

    @Override
    public void addStock(int stock) {
        for(int i = 0; i < stock; i++) {
            commodityDao.addStock(KEY,"智能手表");
        }
    }

    @Override
    public String spike() {
        return commodityDao.spike(KEY);
    }
}

测试功能

@SpringBootTest
@RunWith(SpringRunner.class)
public class RedisTest {

    @Autowired
    private CommodityService commodityService;

    /**
     * 执行商品秒杀前,将商品存入数据库中,已存入5件商品
     */
    @Before
    public void addStock() {
        commodityService.addStock(5);
    }

    /**
     * 商品秒杀测试,使用两个线程一起秒杀
     */
    @Test
    public void spike() {
        ExecutorService es = Executors.newFixedThreadPool(3);
        Object obj = new Object();
        es.submit(() -> {
            System.out.println(Thread.currentThread().getName() + "正在秒杀");
            while (true) {
                String commodity = commodityService.spike();
                if (commodity != null) {
                    System.out.println(Thread.currentThread().getName() + "抢到了商品" + commodity);
                } else {
                    System.out.println("商品被抢完了");
                    break;
                }
            }
        });
        es.submit(() -> {
            System.out.println(Thread.currentThread().getName() + "正在秒杀");
            while (true) {
                String commodity = commodityService.spike();
                if (commodity != null) {
                    System.out.println(Thread.currentThread().getName() + "抢到了商品" + commodity);
                } else {
                    System.out.println("商品被抢完了");
                    break;
                }
            }
        });
    }
    
    /**
     * 单线程环境秒杀
     */
    @Test
    public void del() {
        while (true) {
            String commodity = commodityService.spike();
            if (commodity != null) {
                System.out.println(Thread.currentThread().getName() + "抢到了商品" + commodity);
            } else {
                System.out.println("商品被抢完了");
                break;
            }
        }
    }
}

你可能感兴趣的:(Spring,数据库,redis,java,spring,boot)