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.
- Redis
- MySQL
- Maven
- Java
- Lua
- Spring Boot
- Spring
- Spring MVC
- MyBatis
-
Clone this project in
IntelliJ IDEA
; -
Modify
\src\main\resources\application-dev.properties
:- Modify
spring.datasource.username
andspring.datasource.password
to your own MySQL username and password; - Modify
spring.datasource.url
andblackfriday.database.url
to your current time zone;
- Modify
-
Start your local Redis server;
-
Run
\src\main\java\com\singfung\blackfriday\CyberBlackFridayApplication
(click the triangle near the line numbers). After that, databaseblackfriday
should have been created in your local MySQL; -
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
.
Here are a few steps to create the scene that lots of people are ordering the same product at the same time:
- 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.
- Run
- Enter
stockId
(1 as default) andNumber of Users
on the browser; - 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.
-
- Check the database to see how much time was spent on the emulation.
- Click
Reset
to clear all records in MySQL and Redis. Start another emulation by redoing all these steps again.
-
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).
-
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.
-
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.
-
Parameters: stockNum = 20,000, number of users = 21,000;
-
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
Not only does Redis prevent the system from generating excess orders, but it also helps decrease runtime significantly.
- The main idea of this project is from a Chinese book called Java EE 互联网轻量级框架整合开发. However, I made a lot of improvements on it.
- The Black Friday image was found on this link.