当前位置:网站首页>Design and implementation of secsha system
Design and implementation of secsha system
2022-07-05 23:12:00 【Bald and weak.】
List of articles
Write it at the front
Second kill is no stranger to everyone , And it is a necessary skill point for e-commerce projects .
But the real secsha service is very complicated , Second kill has the characteristics of instant high concurrency , So solve the problem of instant high concurrency , Can solve the problem of second kill .
Today, we will decompose the complete implementation of secsha system , Let's study it together .
( Please correct any questions )
Precautions for seckill system
Single responsibility for service + Independent deployment
There are great risks in seckill service , Carelessness will cause service downtime or occupy a lot of server resources in an instant , therefore Seckill service must be deployed independently , And seckill service only does seckill function .
Seckill link encryption
Prevent malicious attacks , Prevent someone from simulating the seckill request, causing greater pressure on the server ;
Prevent link exposure , Prevent staff from killing goods in advance .
Stock preheating + Quick deduction
Second kill system reads more and writes less , We can preheat the total inventory first , Deposit in redis in , Use semaphores to control the number of seckill requests .
Dynamic and static separation
Use nginx Do a good job of separating the static from the dynamic , Ensure that static resources can directly request , Avoid consuming backend resources .( Now they are basically front and back-end separation projects , It's negligible here )
Malicious request interception
Identify the request of illegal attack and intercept , It can be intercepted from the gateway layer , Determine whether the user is logged in .
Flow peak shifting
By all means , Sharing traffic to a wider range of time points . For example, verification code 、 Add to cart , Add a few more steps .
Current limiting & Fuse & Downgrade
Front end current limiting + Back end current limiting .
Limit one click per second ; Limit the total amount ;
Back end fast failure 、 Degraded operation 、 Circuit breaker mechanism prevents avalanche .
Queue clipping
Second kill all successful products , Put it in the message queue , Then the consumer slowly creates orders and other logic .
Concrete realization
Current limiting fuse
Use sentinel Carry out current limiting
Detailed explanation sentinel: Traffic guard of distributed system
Queue clipping
Use rockerMQ perhaps rabbitMQ Peak clipping .
Stock preheating
Using scheduled tasks , Send the product information in advance 、 Commodity random code ( Prevent malicious attacks )、 Information such as commodity inventory is stored redis.
Pseudo code :
/** * Cache the product information associated with the second kill activity */
private void saveProductInfo(List<Product> products) {
products.stream().forEach(products-> {
// Get ready hash operation , binding hash
BoundHashOperations<String, Object, Object> operations = redisTemplate.boundHashOps(SECKILL_CHARE_PREFIX);
products.getRelationSkus().stream().forEach(seckillSkuVo -> {
// Generate random code
String token = UUID.randomUUID().toString().replace("-", "");
String redisKey = seckillSkuVo.getPromotionSessionId().toString() + "-" + seckillSkuVo.getSkuId().toString();
if (!operations.hasKey(redisKey)) {
// Prevent duplicate addition
// Cache our product information
SeckillSkuRedisTo redisTo = new SeckillSkuRedisTo();
Long skuId = seckillSkuVo.getSkuId();
//1、 First, check the basic information of the goods , Call remote service
R info = productFeignService.getSkuInfo(skuId);
if (info.getCode() == 0) {
SkuInfoVo skuInfo = info.getData("skuInfo",new TypeReference<SkuInfoVo>(){
});
redisTo.setSkuInfo(skuInfo);
}
//2、sku Second kill information
BeanUtils.copyProperties(seckillSkuVo,redisTo);
//3、 Set the second kill time information of the current product
redisTo.setStartTime(session.getStartTime().getTime());
redisTo.setEndTime(session.getEndTime().getTime());
//4、 Set random code of goods ( Prevent malicious attacks )
redisTo.setRandomCode(token);
// serialize json Format deposit Redis in
String seckillValue = JSON.toJSONString(redisTo);
operations.put(seckillSkuVo.getPromotionSessionId().toString() + "-" + seckillSkuVo.getSkuId().toString(),seckillValue);
// If the commodity inventory information of the current session has been put on the shelf, it does not need to be put on the shelf
//5、 Use inventory as distributed Redisson Semaphore ( Current limiting )
// Use inventory as a distributed semaphore
RSemaphore semaphore = redissonClient.getSemaphore(SKU_STOCK_SEMAPHORE + token);
// The number of goods can be killed in seconds as a semaphore
semaphore.trySetPermits(seckillSkuVo.getSeckillCount());
}
});
});
}
Second kill
/** * Second kill of goods ( The second kill begins ) * @param killId * @param key * @param num * @return */
@GetMapping(value = "/kill")
public String seckill(@RequestParam("killId") String killId,
@RequestParam("key") String key,
@RequestParam("num") Integer num,
Model model) {
String orderSn = null;
try {
//1、 Determine whether to log in
orderSn = seckillService.kill(killId,key,num);
model.addAttribute("orderSn",orderSn);
} catch (Exception e) {
e.printStackTrace();
}
return "success";
}
/** * Second kill the current product ( The second kill begins ) * @param killId * @param key * @param num * @return */
@Override
public String kill(String killId, String key, Integer num) throws InterruptedException {
long s1 = System.currentTimeMillis();
// Get current user information
MemberResponseVo user = LoginUserInterceptor.loginUser.get();
//1、 Get the details of the current second kill product from Redis In order to get
BoundHashOperations<String, String, String> hashOps = redisTemplate.boundHashOps(SECKILL_CHARE_PREFIX);
String skuInfoValue = hashOps.get(killId);
if (StringUtils.isEmpty(skuInfoValue)) {
return null;
}
//( Validity test )
SeckillSkuRedisTo redisTo = JSON.parseObject(skuInfoValue, SeckillSkuRedisTo.class);
Long startTime = redisTo.getStartTime();
Long endTime = redisTo.getEndTime();
long currentTime = System.currentTimeMillis();
// Judge whether the current second kill request is within the active time interval ( Validity of time )
if (currentTime >= startTime && currentTime <= endTime) {
//2、 Verify random codes and Commodities id
String randomCode = redisTo.getRandomCode();
String skuId = redisTo.getPromotionSessionId() + "-" +redisTo.getSkuId();
if (randomCode.equals(key) && killId.equals(skuId)) {
//3、 Verify whether the shopping quantity is reasonable and whether the inventory is sufficient
Integer seckillLimit = redisTo.getSeckillLimit();
// Acquisition semaphore
String seckillCount = redisTemplate.opsForValue().get(SKU_STOCK_SEMAPHORE + randomCode);
Integer count = Integer.valueOf(seckillCount);
// Judge whether the semaphore is greater than 0, And you can't buy more than you have in stock
if (count > 0 && num <= seckillLimit && count > num ) {
//4、 Verify that this person has bought ( Idempotent treatment ), If the second kill succeeds , Just take a seat .userId-sessionId-skuId
//SETNX Atomic treatment
String redisKey = user.getId() + "-" + skuId;
// Set auto expiration ( End time - current time )
Long ttl = endTime - currentTime;
Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent(redisKey, num.toString(), ttl, TimeUnit.MILLISECONDS);
if (aBoolean) {
// A successful space occupation means that you have never bought , Distributed lock ( Acquisition semaphore -1)
RSemaphore semaphore = redissonClient.getSemaphore(SKU_STOCK_SEMAPHORE + randomCode);
//TODO Seckill success , Order quickly
boolean semaphoreCount = semaphore.tryAcquire(num, 100, TimeUnit.MILLISECONDS);
// Guarantee Redis There is also a stock of goods
if (semaphoreCount) {
// Create an order number and send the order information to MQ
// Seckill success Order quickly Send a message to MQ The whole operation time is 10ms about
String timeId = IdWorker.getTimeId();
SeckillOrderTo orderTo = new SeckillOrderTo();
orderTo.setOrderSn(timeId);
orderTo.setMemberId(user.getId());
orderTo.setNum(num);
orderTo.setPromotionSessionId(redisTo.getPromotionSessionId());
orderTo.setSkuId(redisTo.getSkuId());
orderTo.setSeckillPrice(redisTo.getSeckillPrice());
rabbitTemplate.convertAndSend("order-event-exchange","order.seckill.order",orderTo);
long s2 = System.currentTimeMillis();
log.info(" Time consuming ..." + (s2 - s1));
return timeId;
}
}
}
}
}
long s3 = System.currentTimeMillis();
log.info(" Time consuming ..." + (s3 - s1));
return null;
}
redisson Semaphore
redisson Use the total solution ——redisson Official documents + notes ( medium-length )
边栏推荐
- Krypton Factor purple book chapter 7 violent solution
- Development specification: interface unified return value format [resend]
- LeetCode102. Sequence traversal of binary tree (output by layer and unified output)
- [untitled]
- 一文搞定class的微观结构和指令
- Use of metadata in golang grpc
- Roman numeral to integer
- d3dx9_ What if 29.dll is missing? System missing d3dx9_ Solution of 29.dll file
- Krypton Factor-紫书第七章暴力求解
- Initial experience | purchase and activate typora software
猜你喜欢
Registration of Electrical Engineering (elementary) examination in 2022 and the latest analysis of Electrical Engineering (elementary)
Hainan Nuanshen tea recruits warmhearted people: recruitment of the product experience recommender of Nuanshen multi bubble honey orchid single cluster
2022 R2 mobile pressure vessel filling review simulation examination and R2 mobile pressure vessel filling examination questions
Basic knowledge of database (interview)
LabVIEW打开PNG 图像正常而 Photoshop打开得到全黑的图像
[digital signal denoising] improved wavelet modulus maxima digital signal denoising based on MATLAB [including Matlab source code 1710]
Go语言实现原理——锁实现原理
Fix the memory structure of JVM in one article
14种神笔记方法,只需选择1招,让你的学习和工作效率提高100倍!
One article deals with the microstructure and instructions of class
随机推荐
[digital signal denoising] improved wavelet modulus maxima digital signal denoising based on MATLAB [including Matlab source code 1710]
TypeError: this. getOptions is not a function
【原创】程序员团队管理的核心是什么?
Déterminer si un arbre binaire est un arbre binaire complet
How to quickly understand complex businesses and systematically think about problems?
一文搞定JVM常见工具和优化策略
Selenium+pytest automated test framework practice
Use of shell:for loop
openresty ngx_ Lua request response
派对的最大快乐值
[speech processing] speech signal denoising and denoising based on Matlab GUI low-pass filter [including Matlab source code 1708]
Development specification: interface unified return value format [resend]
【Note17】PECI(Platform Environment Control Interface)
(4)UART应用设计及仿真验证2 —— TX模块设计(无状态机)
Multi view 3D reconstruction
Vision Transformer (ViT)
Element operation and element waiting in Web Automation
如何快速理解复杂业务,系统思考问题?
Selenium+Pytest自动化测试框架实战
Multi sensor fusion of imu/ optical mouse / wheel encoder (nonlinear Kalman filter)