/cyber-black-friday

Emulate the scene that thousands of people buy the same product at the same time, see how efficient the system would become after being integrated with Redis.

Primary LanguageJava

Cyber Black Friday

Imagine that thousands of people are going to buy the same product at the same time on Cyber Black Friday, how should the shopping system be designed so that it won't crash or perform poorly when it is bombarded with orders?

In this project, I tested how efficient it could become when an online shopping system is integrated with Redis.

Prerequisites

  • Redis
  • MySQL
  • Maven
  • Java

Other frameworks

  • Lua
  • Spring Boot
  • Spring
  • Spring MVC
  • MyBatis

How to run this project

  1. Clone this project in IntelliJ IDEA;

  2. Modify \src\main\resources\application-dev.properties:

    1. Modify spring.datasource.username and spring.datasource.password to your own MySQL username and password;
    2. Modify spring.datasource.url and blackfriday.database.url to your current time zone;
  3. Start your local Redis server;

  4. Run \src\main\java\com\singfung\blackfriday\CyberBlackFridayApplication(click the triangle near the line numbers). After that, database blackfriday should have been created in your local MySQL;

  5. Open http://localhost:8080/ in Firefox.

    P.S. Chrome is not recommended in this project. When the number of users is too large, it will show the following error: Failed to load resource: net::ERR_INSUFFICIENT_RESOURCES.

Emulate an explosion of orders

Here are a few steps to create the scene that lots of people are ordering the same product at the same time:

  1. Add a product into stock. Before that you need to decide how many products there would be in stock, and then do one of the following to add it to DB and Redis:
    • Run \api-examples\insert-stock-record.http if you are using IntelliJ IDEA Ultimate;
    • Copy the content from \api-examples\insert-stock-record.http to Postman and run it.
  2. Enter stockId (1 as default) and Number of Users on the browser;
  3. Click one of the two buttons to start an emulation:
    • Order: implemented using pessimistic locking. The corresponding row in stock table would be locked when stockNum decreases.

      IntelliJ Console will show Orders are full! when the stock is empty.

    • Order with Redis: implemented using Redis. All orders would be saved into Redis before being transferred into MySQL when the stock is empty. The reason why the combination of Redis and Lua could prevent the system from generating excess orders is explained here.

      IntelliJ Console will show a message when the whole process is complete.

  4. Check the database to see how much time was spent on the emulation.
  5. Click Reset to clear all records in MySQL and Redis. Start another emulation by redoing all these steps again.

Experimental environment

  • Ubuntu 18.04.4

  • Redis 6.2.4

  • MySQL 8.0.25

  • Firefox

    It is perfectly okay to run this project on Windows. However, the Redis project does not officially support Windows (you can install the Windows one that was developed by Microsoft on this link whose latest release is 3.0.504).

Test cases

Case 1: No method is applied to prevent error

  • Parameters: stockNum = 100, number of users = 200;

  • Result:

  • Analysis: Although there were only 100 products in stock, 108 orders were generated, which is definitely not accepted.

Case 2: Pessimistic locking

  • Parameters: stockNum = 2,000, number of users = 3,000;

  • Results:

  • Analysis: It generated exactly 2,000 orders, however, it took more than 5 minutes to finish the whole process.

Case 3: Redis

  • Parameters: stockNum = 20,000, number of users = 21,000;

  • Results:

  • Analysis: It generated exactly 20,000 orders, and it took only around 16s to finish the whole process.

    Time of Time
    sending requests from browser ≈ 2s
    generating orders in Redis ≈ 14s
    transferring orders from Redis to DB ≈ 1s
    the whole process ≈ 16s

Conclusion

Not only does Redis prevent the system from generating excess orders, but it also helps decrease runtime significantly.

Credit