In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-04-03 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >
Share
Shulou(Shulou.com)05/31 Report--
This article mainly introduces the relevant knowledge of "how to achieve the second kill system in redis". The editor shows you the operation process through the actual case. The operation method is simple, fast and practical. I hope this article "how to achieve the second kill system in redis" can help you solve the problem.
First, design ideas
The characteristic of the second kill system is that the amount of concurrency is large, tens of thousands of requests may come in in a second, and if you don't use some means, the system will collapse in minutes. Let's discuss how to design a second kill system that can play.
1. Current restriction:
First of all, regardless of business logic, if you have the following simplest interface:
@ GetMapping ("/ test")
Public String test () {
Return "success"
}
This is the simplest interface without any logic, but if there are thousands of requests to access the interface at the same time, the server will crash. Therefore, the first thing a highly concurrent system should do is to limit the current. Springcloud projects can use hystrix to limit current, and springcloud alibaba can use sentinel to limit current. What about non-springcloud projects? Guava provides us with a RateLimiter utility class that can be used as a current limiter. It mainly includes leaky bucket algorithm and token bucket algorithm.
Leaky bucket algorithm: a bucket with a hole is filled with water under the faucet, which leaks a little, but if the water in the faucet is very large, the water in the bucket will overflow sooner or later, and the overflow will limit the flow. This is suitable for limiting the upload and download rate and so on.
Token bucket algorithm: put tokens into the bucket at a constant rate. Every time a request comes in, you have to get the token from the bucket first. If you don't get the token, the request is blocked. This is suitable for current limiting, that is, limiting QPS.
Here, you should use the token bucket algorithm to limit the current, and if you don't get the token, directly return the prompt that "there are too many people to squeeze in".
2. Check whether the user is logged in:
After the flow restriction in the first step, the incoming request should check whether the user is logged in. This project uses JWT, that is, request login API first, log in and return token, request all other APIs to put token in the request header, and then get the user information through token. If you do not get the user information, the prompt "invalid token, please log in again" is returned.
3. Check whether the goods are sold out:
After passing the verification of the first two steps, you should check whether the goods have been sold out, and if they are sold out, you will return the hint that "it is too late, the goods have been killed in seconds". Note that check whether the goods are sold out can not check the database, otherwise it will be very slow. We can create a map, the commodity id as key, if sold out, the value is set to true, otherwise it is false.
4. Add the products that participate in the second kill to redis:
First, create a key of ISINREDIS to indicate whether the item has been added to the redis to avoid repeating this operation with each request. If the ISINREDIS value is false, there are no second kill items in redis. Then find out all the goods that participated in the second kill, the commodity id as key, the commodity inventory as value, stored in redis, and the commodity id as key,false as value, put into the map of the third step, indicating that the product is not sold out. Finally, set the value of ISINREDIS to true, indicating that all the items participating in the second kill have been added to the redis.
5. Withholding inventory:
Use the decr of redis to self-subtract the goods, and then judge the results after the self-subtraction. If the result after deduction is less than 0, indicating that the goods have been sold out, then set the value of the id of the corresponding goods in map to true, and return the prompt that "it is too late, the goods have been killed in seconds".
6. Judge whether to repeat the second kill:
If the instant kill is successful, the user id and product id will be stored in redis as key,true as value after the second kill order is entered, indicating that the user has killed the product in seconds. So here according to the user id and product id to determine whether to repeat the second kill in the redis, if so, return the prompt of "do not repeat the second kill".
7. Asynchronous processing:
If all the above checks are passed, then the second kill can be handled. However, if we deal with every second kill request, we deduct inventory and create orders in the database, which is also very slow and may crush the database. So we can handle it asynchronously, that is, after passing the above check, we send the user id and the product id to MQ as message, and then immediately return the prompt "in queue" to the user. Then consume the message at the consumer end of the MQ, get the user id and the product id, and query the inventory according to the product id to ensure that the inventory is sufficient again; then you can again determine whether to repeat the second kill. After passing the judgment, operate the database, deduct inventory, and create a second kill order. Note that the inventory deduction and the creation of the kill order need to be in the same transaction.
8. Oversold problem:
The problem of overselling is that the inventory of goods is negative. For example, the inventory remaining 1, and then 10 users at the same time kill, when judging the inventory is 1, so 10 people can place an order successfully, the final inventory is-9. How to solve? In fact, there is no such problem in this system at all, because at the beginning, inventory reduction is carried out with redis, and the core module of redis command is single-threaded, so it can be guaranteed that it will not be oversold. If redis is not used, you can also add a version field to the item. Check its version before deducting inventory each time, and add a condition to the sql of deducting inventory, that is, version should be equal to the version just found out.
Second, the core code @ RestController
@ RequestMapping ("/ seckill")
Public class SeckillController {
@ Autowired
Private UserService userService
@ Autowired
Private SeckillService seckillService
@ Autowired
Private RabbitMqSender mqSender
/ / key used to mark whether the product has been added to the redis
Private static final String ISINREDIS = "isInRedis"
/ / use goodsId as key to mark whether the item has been sold out
Private Map seckillOver = new HashMap ()
/ / use RateLimiter as current limit, create (10), it can be understood that the QPS threshold is 10
Private RateLimiter rateLimiter = RateLimiter.create (10)
@ PostMapping ("/ {sgId}")
Public JsonResult seckillGoods (@ PathVariable ("sgId") Integer sgId, HttpServletRequest httpServletRequest) {
/ / 1. If the QPS threshold exceeds 10, that is, if you don't get a token within 1 second, the prompt "there are too many people to squeeze in" will be returned.
If (! rateLimiter.tryAcquire (1, TimeUnit.SECONDS)) {
Return new JsonResult (SeckillGoodsEnum.TRY_AGAIN.getCode (), SeckillGoodsEnum.TRY_AGAIN.getMessage ())
}
/ / 2. Check whether the user is logged in (after the user logs in, token should be put on the request header to access each interface, and then get the user according to the token)
String token = httpServletRequest.getHeader ("token")
String userId = JWT.decode (token). GetAudience (). Get (0)
User user = userService.findUserById (Integer.valueOf (userId))
If (user = = null) {
Return new JsonResult (SeckillGoodsEnum.INVALID_TOKEN.getCode (), SeckillGoodsEnum.INVALID_TOKEN.getMessage ())
}
/ / 3. If the product has been killed in seconds, do not execute the following logic and return to the prompt that the product has been killed in seconds.
If (! seckillOver.isEmpty () & & seckillOver.get (sgId)) {
Return new JsonResult (SeckillGoodsEnum.SECKILL_OVER.getCode (), SeckillGoodsEnum.SECKILL_OVER.getMessage ())
}
/ / 4. Add all the product information that participated in the second kill to the redis.
If (! RedisUtil.isExist (ISINREDIS)) {
List goods = seckillService.getAllSeckillGoods ()
For (SeckillGoods seckillGoods: goods) {
RedisUtil.set (String.valueOf (seckillGoods.getSgId ()), seckillGoods.getSgSeckillNum ())
SeckillOver.put (seckillGoods.getSgId (), false)
}
RedisUtil.set (ISINREDIS, true)
}
/ / 5. Reduce the inventory first, withhold the inventory in advance, and judge whether the inventory after withholding is less than 0. If so, it means that the stock is finished.
Long stock = RedisUtil.decr (String.valueOf (sgId))
If (stock < 0) {
/ / Mark that the product has been killed in seconds.
SeckillOver.put (sgId, true)
Return new JsonResult (SeckillGoodsEnum.SECKILL_OVER.getCode (), SeckillGoodsEnum.SECKILL_OVER.getMessage ())
}
/ / 6. Determine whether to repeat the second kill (after the second kill is successful and the order is created, userId and goodsId will be put into redis as key)
If (RedisUtil.isExist (userId + sgId)) {
Return new JsonResult (SeckillGoodsEnum.REPEAT_SECKILL.getCode (), SeckillGoodsEnum.REPEAT_SECKILL.getMessage ())
}
/ / 7. If all the above checks are passed, the current request is added to the MQ and the prompt "in queue" is returned.
String msg = userId + "," + sgId
MqSender.send (msg)
Return new JsonResult (SeckillGoodsEnum.LINE_UP.getCode (), SeckillGoodsEnum.LINE_UP.getMessage ())
}
}
3. Pressure test
Use jmeter to simulate concurrent requests to test whether the system can withstand high concurrency. Since there is only one item with an id of 1, the commodity id is always written as 1. However, every user has to request the login API to obtain the token before making the second kill request, so you can comment out the jwt module and pass the userId as a parameter. The jmeter configuration is shown below:
Jmeter stress test configuration jmeter stress test configuration on "redis how to achieve second kill system" content is introduced here, thank you for reading. If you want to know more about the industry, you can follow the industry information channel. The editor will update different knowledge points for you every day.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.