当前位置:网站首页>Seckill system 03 - redis cache and distributed lock
Seckill system 03 - redis cache and distributed lock
2022-07-01 11:46:00 【v_ BinWei_ v】
Seckill system 03—— Multi level cache
cache :
Background problem description
Access the database to query product information :
Read more and write less
Front end static page :
In the first part, we staticize the data , There are also many problems , For example, if we have too many goods ,freemark The template must be modified , All our goods need to be re produced and static , This workload is really too much .
Introduce caching :
Caching :
![[ Failed to transfer the external chain picture , The origin station may have anti-theft chain mechanism , It is suggested to save the pictures and upload them directly (img-YcvUmFV9-1644933832299)(G:\ Technology accumulation \ Billion level concurrent programming e-commerce \ Seckill system .assets\clipboard-1644926587622.png)]](/img/20/49a6a0237508181321d50e3f43c4b0.jpg)
Redis Cache practice :
Join in Redis
/** * Get product details Join in redis * * @param id product ID */
public PmsProductParam getProductInfo2(Long id) {
PmsProductParam productInfo = null;
// From the cache Redis Look inside
productInfo = redisOpsUtil.get(RedisKeyPrefixConst.PRODUCT_DETAIL_CACHE + id, PmsProductParam.class);
if (null != productInfo) {
return productInfo;
}
productInfo = portalProductDao.getProductInfo(id);
System.out.println(" I was executed ");
if (null == productInfo) {
log.warn(" No product information was found ,id:" + id);
return null;
}
checkFlash(id, productInfo);
redisOpsUtil.set(RedisKeyPrefixConst.PRODUCT_DETAIL_CACHE + id, productInfo, 3600, TimeUnit.SECONDS);
return productInfo;
}
The problem of the above scheme : Data copy 、 Common problems of data caching
1、 The problem of data consistency , How to guarantee Redis and mysql The problem of data consistency
Jmeter 1000 Secondary request graph , throughput 630.5/sec
![[ Failed to transfer the external chain picture , The origin station may have anti-theft chain mechanism , It is suggested to save the pictures and upload them directly (img-5gkiQ3we-1644933832301)(G:\ Technology accumulation \ Billion level concurrent programming e-commerce \ Seckill system .assets\clipboard-1644929409321.png)]](/img/a1/34ac597e7ae2f318cdcc0e3e44cd0c.jpg)
Two solutions for data consistency :
1、 The final consistency plan :
Set timeout to resolve . Set up Redis Timeout for caching data .Redis Be overdue , The next request must be from mysql In order to get
redisOpsUtil.set(RedisKeyPrefixConst.PRODUCT_DETAIL_CACHE+id,productInfo,360,TimeUnit.SECONDS);
2、 Real time consistency scheme :
transaction canal binlog
Two questions ( High concurrency )
The problem of compression 、 Reduce memory
problem 1,Redis Cached objects are sometimes large ,Redis Only disk IO, There is no solution to the network IO problem . Network transmission IO Still big .
problem 2,Redis Data will occupy a lot of memory , Using expiration mechanism can relieve memory pressure .
The Internet I/O resolvent , Compress object content , Using serialization and compression
Stress test scenario
The current in jmeter Carry out inside 1000 Concurrent request items id=26, The results are as follows
![[ Failed to transfer the external chain picture , The origin station may have anti-theft chain mechanism , It is suggested to save the pictures and upload them directly (img-OHATeXTn-1644933832303)(G:\ Technology accumulation \ Billion level concurrent programming e-commerce \ Seckill system .assets\clipboard-1644928595174.png)]](/img/27/56b86a53bd4d901cebaa01a7fe53a4.jpg)
As expected, only set once redis There are differences , Why is it like this ?
re: Because of the emergence of Concurrency issues .
When I visit again for the second time , There is no log output at this time , It means that all caches are gone
Concurrency issues : Concurrent programming 》 Concurrency issues 》 It can be achieved by locking java Concurrent , But the way of locking ( Not suitable for Distributed scenarios )
Why is locking not suitable for distributed scenarios :
scene : If there is 800 A request ,400 To access a server ,400 One to access another server .
Which is locked synchronized One of them can be guaranteed jvm Of 400 The first request is serial access .
But the order in which two servers access the database cannot be guaranteed , Whether it is cross process access .
Lock time 、 And the running time of the code block
resolvent : Using distributed locks :redis、zookeeper
zookeeper Strong certification , Suitable for distributed
Redis Distributed Combat
/* * zk Distributed lock */
@Autowired
private ZKLock zkLock;
private String lockPath = "/load_db";
@Autowired
RedissonClient redission;
/** * Get product details Join in redis Join the lock * * @param id product ID */
public PmsProductParam getProductInfo3(Long id) {
PmsProductParam productInfo = null;
// From the cache Redis Look inside
productInfo = redisOpsUtil.get(RedisKeyPrefixConst.PRODUCT_DETAIL_CACHE + id, PmsProductParam.class);
if (null != productInfo) {
return productInfo;
}
RLock lock = redission.getLock(lockPath + id); // Gets a reentrant lock
try {
if (lock.tryLock()) {
// Get the lock - The same thread can re-enter
productInfo = portalProductDao.getProductInfo(id);
if (null == productInfo) {
log.warn(" No product information was found ,id:" + id);
return null;
}
checkFlash(id, productInfo);
redisOpsUtil.set(RedisKeyPrefixConst.PRODUCT_DETAIL_CACHE + id, productInfo, 3600, TimeUnit.SECONDS);
} else {
productInfo = redisOpsUtil.get(RedisKeyPrefixConst.PRODUCT_DETAIL_CACHE + id, PmsProductParam.class);
}
} finally {
if (lock.isLocked()) {
if (lock.isHeldByCurrentThread())
lock.unlock();
}
}
return productInfo;
}
ps: Definition of reentry lock and deflection lock
Reentrant lock , Reentrancy means, for example, that a thread acquires an object A The lock on the , If it requests a second time A Your lock must be available ( That is to say, I won't lock myself up ), Reentrancy is what threads must meet , Otherwise, a lot of code will deadlock
Biased locking , Biased locking means that if a thread requests a lock that it has already obtained , It won't do it again lock and unlock, This improves performance .
How to achieve reentrant is the same , Is to write down the owner of the lock , When applying for a lock, check whether the lock has been occupied , If someone occupies the lock , See if it is the applicant himself .
You can see that it works Redis lock ,QPS Immediately improved a lot
![[ Failed to transfer the external chain picture , The origin station may have anti-theft chain mechanism , It is suggested to save the pictures and upload them directly (img-5WxTzsiC-1644933832303)(G:\ Technology accumulation \ Billion level concurrent programming e-commerce \ Seckill system .assets\image-20220215213855319.png)]](/img/a1/34ac597e7ae2f318cdcc0e3e44cd0c.jpg)
Redis Self provided lock setnx, Use setnx Concurrent lock
Cache application scenario :
1、 Large amount of visits 、QPS high 、 Businesses with low update frequency
2、 Data consistency requirements are not high
Redis The cache problem
Cache breakdown problem ( Hotspot data is single key):
For some with expiration set key, If these key May be in Some points in time are accessed very concurrently , It's a very “ hotspot ” The data of . This is the time , A question needs to be considered : The cache is “ breakdown ” The problem of , The difference between this and cache avalanche is that this is for a certain key cache , The former is a lot of key, Cache breakdown is for a key A period of time in which to visit .
![[ Failed to transfer the external chain picture , The origin station may have anti-theft chain mechanism , It is suggested to save the pictures and upload them directly (img-w2Hu0De0-1644933832304)(G:\ Technology accumulation \ Billion level concurrent programming e-commerce \ Seckill system .assets\clipboard-1644932539827.png)]](/img/1a/520795221a2d4274d84b4bbf004081.jpg)
Solution :
1. Lock , When the cache misses , Avoid a large number of requests to access the database by locking . Through the lock
2. No expiration allowed . Physics doesn't expire , That is, do not set the expiration time . Instead, it updates data in the background asynchronously and regularly . The simplest rough situation
3. Second level cache .L1 Cache expiration time is short ,L2 Cache expiration time is long . Request priority from L1 Get data cache , If you miss , Lock it , Ensure that only one thread reads data from the database and then updates to L1 and L2 in . Then other threads are still L2 Get data cache . Second level cache , It's impossible to have two Redis Are punctured .
Cache penetration problem ( A malicious attack 、 Access nonexistent data ):
Cache penetration refers to querying a certain nonexistent data , Because the cache is written passively on Miss , And for the sake of fault tolerance , If no data can be found from the storage tier, it will not be written to the cache , This will cause the non-existent data to be queried by the storage layer every time it is requested , It loses the meaning of caching . When the flow is large , Probably DB It's gone , If someone Take advantage of the nonexistent key Attack our applications frequently , This is the loophole .
Some people use nonexistent key Visit frequently , Cache penetration will occur
![[ Failed to transfer the external chain picture , The origin station may have anti-theft chain mechanism , It is suggested to save the pictures and upload them directly (img-gRzuvO9e-1644933832305)(G:\ Technology accumulation \ Billion level concurrent programming e-commerce \ Seckill system .assets\clipboard-1644932657752.png)]](/img/22/49d46e37859d44b6312c86ac045982.jpg)
** Solution :** There are many ways to effectively solve the problem of cache penetration
1、 The most common is the use of bloon filter , Hash all possible data to a large enough bitmap in , A certain nonexistent data will be bitmap Intercept , Thus, the query pressure on the underlying storage system is avoided . use The bloon filter
2、 There's also a simpler and rougher way ( This is what we use ), If the data returned by a query is empty ( Whether the data doesn't exist , Or a system failure ), We still cache this empty result , But its expiration time will be very short , Up to five minutes . Directly cache the empty node to Redis in .
![[ Failed to transfer the external chain picture , The origin station may have anti-theft chain mechanism , It is suggested to save the pictures and upload them directly (img-8xbsSNT1-1644933832306)(G:\ Technology accumulation \ Billion level concurrent programming e-commerce \ Seckill system .assets\clipboard-1644932781345.png)]](/img/cb/ff6a467b241806880eae17b67af698.jpg)
Cache avalanche ( At the same time , There's a lot of concurrency ):
Avalanche refers to the use of Same expiration time , Causes the cache to fail at the same time at a certain time , Forward all requests to DB,DB Avalanche with excessive instantaneous pressure .
a large number of Redis At the same time , All interfaces instantly access the database .
![[ Failed to transfer the external chain picture , The origin station may have anti-theft chain mechanism , It is suggested to save the pictures and upload them directly (img-h7v3boW9-1644933832307)(G:\ Technology accumulation \ Billion level concurrent programming e-commerce \ Seckill system .assets\clipboard-1644932910534.png)]](/img/b7/b70502881eb741abc855533e143961.jpg)
![[ Failed to transfer the external chain picture , The origin station may have anti-theft chain mechanism , It is suggested to save the pictures and upload them directly (img-QhnmS8zR-1644933832308)(G:\ Technology accumulation \ Billion level concurrent programming e-commerce \ Seckill system .assets\clipboard-1644932818940.png)]](/img/05/b904298df732efda22494b44a626c4.jpg)
Solution :
**1、** The avalanche effect of cache failure has a terrible impact on the underlying system . Most system designers consider locking or queuing to ensure single thread caching ( process ) Write , So as to avoid a large number of concurrent requests falling on the underlying storage system in case of failure . Here is a simple solution to spread the cache expiration time , For example, we can == A random value is added to the original failure time ==, such as 1-5 Minutes at random , In this way, the repetition rate of each cache expiration time will be reduced , It's hard to trigger a collective failure .
2、 In advance : This solution is to implement the cache cluster before the avalanche High availability , If using Redis, have access to Master-slave + sentry ,Redis Cluster To avoid Redis The total collapse .
3、 In the matter : Use Hystrix Carry out current limiting & Downgrade , For example, a second is coming 5000 A request , We can set the assumption that there is only one second 2000 Requests can go through this component , So the rest 3000 The request will follow the current limiting logic . Then we call our own downgrading component ( Downgrade ), For example, set some default values . To protect the last MySQL Not killed by a lot of requests . Using current limiting & Downgrade
4、 After the event : Turn on Redis Persistence mechanism , Recover the cache cluster as soon as possible . After the avalanche , Quickly recover files
Cache and database write consistency problem :
Consistency problems are common distributed problems , It can also be divided into final consistency and strong consistency . Database and cache write , There are bound to be inconsistencies .
re: First understand a premise . If there is a strong consistency requirement for data , Can't cache .
Everything we do , Only final consistency can be guaranteed . in addition , What we have done is basically , It can only be said to reduce the probability of inconsistency , It is impossible to avoid . therefore , Data with strong consistency requirements , Can't cache .
Introduce distributed lock code :
1、 introduce redis rely on
<!-- Join in redisson-->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.6.5</version>
</dependency>
@Bean
public RedissonClient redissonClient(){
Config config = new Config();
config.useSingleServer().setAddress("redis://tlshop.com:6379").setPassword("123456").setDatabase(1);
return Redisson.create(config);
}
Lock the single machine :
![[ Failed to transfer the external chain picture , The origin station may have anti-theft chain mechanism , It is suggested to save the pictures and upload them directly (img-WGTzjQWp-1644933832309)(G:\ Technology accumulation \ Billion level concurrent programming e-commerce \ Seckill system .assets\clipboard-1644933315086.png)]](/img/5c/caa558aba0e67fd837f6c985ef3af8.jpg)
Distributed locking :
The same data request comes at the same time , such as set 100 value:(1 2 3)
![[ Failed to transfer the external chain picture , The origin station may have anti-theft chain mechanism , It is suggested to save the pictures and upload them directly (img-4nXwbTci-1644933832310)(G:\ Technology accumulation \ Billion level concurrent programming e-commerce \ Seckill system .assets\clipboard-1644933315088.png)]](/img/7d/b59d0cf663e3cdf508cc5c00811f09.jpg)
Use ZooKeeper Distributed lock practice
/** * Get product details * * @param id product ID */
public PmsProductParam getProductInfo(Long id) {
PmsProductParam productInfo = null;
productInfo = redisOpsUtil.get(RedisKeyPrefixConst.PRODUCT_DETAIL_CACHE + id, PmsProductParam.class);
if (productInfo != null) {
log.info("get redis productId:" + productInfo);
return productInfo;
}
try {
if (zkLock.lock(lockPath + "_" + id)) {
productInfo = portalProductDao.getProductInfo(id);
if (null == productInfo) {
return null;
}
checkFlash(id, productInfo);
log.info("set db productId:" + productInfo);
// Cache expiration time is random
redisOpsUtil.set(RedisKeyPrefixConst.PRODUCT_DETAIL_CACHE + id, productInfo, 3600, TimeUnit.SECONDS);
} else {
// problem : Return to null
productInfo = redisOpsUtil.get(RedisKeyPrefixConst.PRODUCT_DETAIL_CACHE + id, PmsProductParam.class);
}
} finally {
log.info("unlock :" + productInfo);
zkLock.unlock(lockPath + "_" + id);
}
return productInfo;
}
private void checkFlash(Long id, PmsProductParam productInfo) {
FlashPromotionParam promotion = flashPromotionProductDao.getFlashPromotion(id);
if (!ObjectUtils.isEmpty(promotion)) {
productInfo.setFlashPromotionCount(promotion.getRelation().get(0).getFlashPromotionCount());
productInfo.setFlashPromotionLimit(promotion.getRelation().get(0).getFlashPromotionLimit());
productInfo.setFlashPromotionPrice(promotion.getRelation().get(0).getFlashPromotionPrice());
productInfo.setFlashPromotionRelationId(promotion.getRelation().get(0).getId());
productInfo.setFlashPromotionEndDate(promotion.getEndDate());
productInfo.setFlashPromotionStartDate(promotion.getStartDate());
productInfo.setFlashPromotionStatus(promotion.getStatus());
}
It is found that the distributed lock added under the high parallel can solve the problem just now , But it also reduces qps, So it still depends on the demand
Principle of distributed lock :
zk chart
![[ Failed to transfer the external chain picture , The origin station may have anti-theft chain mechanism , It is suggested to save the pictures and upload them directly (img-bvI1q5At-1644933832310)(G:\ Technology accumulation \ Billion level concurrent programming e-commerce \ Seckill system .assets\image-20220215220108353.png)]](/img/e9/e0b4713e612b256b3c140188a85a45.jpg)
summary :
1、 The thread will directly create the next temporary sequence node under a lock node
2、 If you're not the first node , Just add a node listener to yourself
3、 As long as the last node releases the lock , Go ahead by yourself , It is equivalent to a queuing mechanism
边栏推荐
- Value/set in redis
- Activity workflow engine
- Force button homepage introduction animation
- Raspberry pie 4B installation tensorflow2.0[easy to understand]
- Unittest框架中测试用例编写规范以及如何运行测试用例
- VScode快捷键(最全)[通俗易懂]
- JS date format conversion method
- Shangtang entered the lifting period: the core management voluntarily banned and strengthened the company's long-term value confidence
- S7-1500PLC仿真
- The developer said, "this doesn't need to be tested, just return to the normal process". What about the testers?
猜你喜欢

ABBIRB120工业机器人机械零点位置

Tianrunyun, invested by Tian Suning, was listed: its market value was 2.2 billion Hong Kong, and its first year profit decreased by 75%

Neo4j 中文开发者月刊 - 202206期

Skip the test cases to be executed in the unittest framework

Exposure: a white box photo post processing framework reading notes

深入理解 grpc part1

Deep understanding of grpc part1

Tempest HDMI leak receive 5

Harbor webhook from principle to construction

Emotion analysis based on IMDB comment data set
随机推荐
Question: what professional qualities should test engineers have?
Value/sortedset in redis
伸展树(一) - 概念和C实现
妙啊!MarkBERT
[Maui] add click events for label, image and other controls
Mysql的四个隔离级别是如何实现的 (简要)
redis配置环境变量
Learning summary on June 28, 2022
openinstall:微信小程序跳转H5配置业务域名教程
Wechat applet development - user authorization to log in to "suggestions collection"
华为HMS Core携手超图为三维GIS注入新动能
Can solo be accessed through IPv6?
CAD如何設置標注小數比特
开发说,“ 这个不用测,回归正常流程就行 “,测试人员怎么办?
Matrix of numpy
Value/hush in redis
Impressive bug summary (continuously updated)
Neo4j Chinese developer monthly - issue 202206
Kafuka learning path (I) Kafuka installation and simple use
耐克如何常年霸榜第一名?最新財報答案來了