Anders als die Cache-Penetration bezieht sich die Cache-Aufschlüsselung auf heiße Daten, die sich nicht im Cache, sondern in der Datenbank befinden.
Zum Beispiel: Heiße Nachrichten auf der Homepage, heiße Daten mit einer sehr großen Anzahl gleichzeitiger Besuche. Wenn der Cache abläuft und ausfällt, fragt der Server zu diesem Zeitpunkt die Datenbank ab Wenn gleichzeitig Anfragen an die Datenbank gestellt werden, kann es sein, dass diese sofort überlastet ist.
Zeichne ein einfaches Diagramm, wie unten gezeigt:
Lösung: DB-Abfrage plus verteilte Sperre #🎜 🎜#.
Entsperrte SituationBevor Sie das Problem lösen, werfen Sie zunächst einen Blick auf den unverarbeiteten Code und die Funktionsweise.Produktdetailcode basierend auf der Produkt-ID abfragen
Leeren Sie den Redis-Cache und öffnen Sie ihn 5 Threads werden auf gleichzeitigen Zugriff getestet. Der Testcode lautet wie folgt:Wir gehen davon aus, dass die Datenbank nur einmal abgefragt wird. und die nächsten vier Abfragen werden aus dem Redis-Cache abgerufen, aber das Ergebnis ist:
Es wird auch keine verteilte Sperre hinzugefügt, aber dieser Container wird gesetzt Großer Druck auf die DB.
Wenn es sich um einen einzelnen Server handelt, verwenden Sie einfach direkt die Synchronisierungssperre von Java
# 🎜🎜# Leider stellt das Backend normalerweise einen Cluster bereit und die Synchronisierungssperre von Java kann keine verteilte Sperre implementieren.Redis verteilte Sperre behebt Cache-Ausfälle
Die in Java integrierte Sperre kann nur auf einer einzelnen Maschine angewendet und nicht verteilt werden,
Das können Sie Verwenden Sie Redis, um verteilte Sperren zu implementieren.
Code nach dem Hinzufügen einer verteilten Sperre//根据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();
}
}
Das obige ist der detaillierte Inhalt vonWie die verteilte Redis-Sperre einen Cache-Ausfall verhindert. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!