Home >Database >Redis >How Redis distributed lock prevents cache breakdown

How Redis distributed lock prevents cache breakdown

王林
王林forward
2023-06-03 19:04:371453browse

Cache breakdown

The difference from cache penetration is that cache breakdown refers to hot data that is not in the cache but exists in the database.

For example: hot news on the homepage, hot data with a very large number of concurrent visits, if the cache expires and fails, the server will query the DB. At this time, if a large number of concurrent queries are made to the DB, the DB may be overwhelmed instantly.

Drawed a simple diagram, as shown below:

How Redis distributed lock prevents cache breakdown

Solution: DB query plus distributed lock.

Unlocked situation

Before solving the problem, first take a look at the unprocessed code and operation conditions.

Query product details code based on product ID

How Redis distributed lock prevents cache breakdown

Clear the Redis cache and open 5 threads for concurrent access testing. The test code is as follows :

How Redis distributed lock prevents cache breakdown


We expected that the DB would only be queried once, and the next four queries would be fetched from the Redis cache, but the result was:
How Redis distributed lock prevents cache breakdown
There is no distributed lock, and the result is expected. However, the container puts a lot of pressure on the DB.

If it is a single server, just use Java's synchronization lock directly

How Redis distributed lock prevents cache breakdown

Unfortunately, usually after The client will deploy a cluster, and Java's synchronization lock cannot implement distributed locks.

Redis distributed lock solves cache breakdown

Java's built-in lock can only be applied on a single machine and cannot be distributed. It can be achieved using Redis. Distributed lock.

Code after adding distributed lock

//根据ID查询商品
@GetMapping("/{id}")
public R id(@PathVariable String id){
	//先查Redis缓存
	Object o = redisTemplate.opsForValue().get(id);
	if (o != null) {
		//命中缓存
		System.err.println("id:"+id+",命中redis缓存...");
		return R.success(o);
	}

	//缓存未命中 查询数据库
	String lockKey = "lock" + id;
	//加锁,10s后过期
	for (;;) {
		if (redisTemplate.opsForValue().setIfAbsent(lockKey, System.currentTimeMillis(), 10L, TimeUnit.SECONDS)) {
			//加锁成功的线程,再次检查
			o = redisTemplate.opsForValue().get(id);
			if (o != null) {
				//命中缓存
				System.err.println("Thread:" + Thread.currentThread().getName() + ",id:"+id+",命中redis缓存...");
				//释放锁
				redisTemplate.delete(lockKey);
				return R.success(o);
			}

			//仍未命中
			System.err.println("Thread:" + Thread.currentThread().getName() + ",id:" + id + ",查询DB...");
			Goods goods = goodsMapper.selectById(id);
			//结果存入Redis
			redisTemplate.opsForValue().set(id, goods);
			//释放锁
			redisTemplate.delete(lockKey);
			return R.success(goods);
		}
		//竞争不到锁,暂时让出CPU资源
		Thread.yield();
	}
}

Start 5 threads for concurrent access. The result is as follows:

How Redis distributed lock prevents cache breakdown

The above is the detailed content of How Redis distributed lock prevents cache breakdown. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:yisu.com. If there is any infringement, please contact admin@php.cn delete