Wie gehe ich mit dem Hotkey-Problem in Redis um? Der folgende Artikel stellt Ihnen gängige Lösungen für das Redis-Cache-Hotkey-Problem vor. Ich hoffe, er wird Ihnen helfen!
Bei einigen C-seitigen Geschäften ist es unvermeidlich, einen First-Level-Cache einzuführen, um den Druck der Datenbank zu ersetzen und die Geschäftsreaktionszeit zu verkürzen. Tatsächlich wird jedes Mal eine Middleware eingeführt, um das Problem zu lösen Dies wird unweigerlich viele neue Probleme mit sich bringen, die Aufmerksamkeit erfordern, beispielsweise die Frage, wie die Cache-Konsistenz erreicht werden kann, die im vorherigen Artikel „Datenbank- und Cache-Konsistenz in der Praxis“ erwähnt wurde. Tatsächlich kann es bei der Verwendung von Redis als Cache der ersten Ebene zu einigen anderen Problemen wie Hotkeys, großen Tasten usw. kommen. In diesem Artikel werden wir den Hotkey (Hotkey) besprechen )
-Problem und wie man das Hotkey
-Problem sinnvoll löst. -
Hintergrund
热key(hot key)
问题来讨论,如何合理的解决
热key
问题。
背景
热key
是什么问题,如何导致的?
一般来说,我们使用的缓存Redis都是多节点的集群版,对某个key进行读写时,会根据该key的hash计算出对应的slot,根据这个slot就能找到与之对应的分片(一个master和多个slave组成的一组redis集群)来存取该K-V。但是在实际应用过程中,对于某些特定业务或者一些特定的时段(比如电商业务的商品秒杀活动),可能会发生大量的请求访问同一个key。所有的请求(且这类请求读写比例非常高)都会落到同一个redis server上,该redis的负载就会严重加剧,此时整个系统增加新redis实例也没有任何用处,因为根据hash算法,同一个key的请求还是会落到同一台新机器上,该机器依然会成为系统瓶颈2,甚至造成整个集群宕掉,若此热点key的value 也比较大,也会造成网卡达到瓶颈,这种问题称为 “热key” 问题。【相关推荐:Redis视频教程】
如下图1、2所示,分别是正常redis cluster集群和使用一层proxy代理的redis 集群key访问。
如上所说,热key会给集群中的少部分节点带来超高的负载压力,如果不正确处理,那么这些节点宕机都有可能,从而会影响整个缓存集群的运作,因此我们必须及时发现热key、解决热key问题。
1.热key探测
热key探测,看到由于redis集群的分散性以及热点key带来的一些显著影响,我们可以通过由粗及细的思考流程来做热点key探测的方案。
1.1 集群中每个slot的qps监控
热key最明显的影响是整个redis集群中的qps并没有那么大的前提下,流量分布在集群中slot不均的问题,那么我们可以最先想到的就是对于每个slot中的流量做监控,上报之后做每个slot的流量对比,就能在热key出现时发现影响到的具体slot。虽然这个监控最为方便,但是粒度过于粗了,仅适用于前期集群监控方案,并不适用于精准探测到热key的场景。
1.2 proxy的代理机制作为整个流量入口统计
如果我们使用的是图2的redis集群proxy代理模式,由于所有的请求都会先到proxy再到具体的slot节点,那么这个热点key的探测统计就可以放在proxy中做,在proxy中基于时间滑动窗口
,对每个key做计数,然后统计出超出对应阈值的key。为了防止过多冗余的统计,还可以设定一些规则,仅统计对应前缀和类型的key。这种方式需要至少有proxy的代理机制,对于redis架构有要求。
1.3 redis基于LFU的热点key发现机制
redis 4.0以上的版本支持了每个节点上的基于LFU的热点key发现机制,使用redis-cli –hotkeys
即可,执行redis-cli时加上–hotkeys选项。可以定时在节点中使用该命令来发现对应热点key。
如下所示,可以看到redis-cli –hotkeys
Hot Key
Wie wird es verursacht?
🎜 Im Allgemeinen handelt es sich bei dem von uns verwendeten Cache-Redis um eine Multi-Node-Cluster-Version. Beim Lesen und Schreiben eines bestimmten Schlüssels wird der entsprechende Slot anhand des Hashs des Schlüssels berechnet und der entsprechende Slot kann auf dieser Grundlage gefunden werden Für den Zugriff auf den K-V wird Sharding (ein Satz von Redis-Clustern bestehend aus einem Master und mehreren Slaves) verwendet. Im eigentlichen Antragsprozess kann es jedoch für bestimmte Unternehmen oder bestimmte Zeiträume (z. B. Produkt-Flash-Sales-Aktivitäten in E-Commerce-Unternehmen) zu einer großen Anzahl von Anfragen kommen, die auf denselben Schlüssel zugreifen. Alle Anfragen (und das Lese-/Schreibverhältnis dieser Anfragen ist sehr hoch) fallen auf denselben Redis-Server, und die Belastung des Redis wird erheblich erhöht. Zu diesem Zeitpunkt wird das Hinzufügen neuer Redis-Instanzen zum gesamten System erforderlich sein Kein Nutzen, da laut Hash-Algorithmus Anfragen für denselben Schlüssel immer noch auf denselben neuen Computer fallen, was immer noch zu einem Systemengpass2 führt und sogar zum Absturz des gesamten Clusters führt, wenn der Wert dieses Hotspot-Schlüssels relativ ist groß, es wird auch dazu führen, dass die Netzwerkkarte den Engpass erreicht. Dieses Problem wird als „Hotkey“-Problem bezeichnet. [Verwandte Empfehlungen:
Redis-Video-Tutorial]🎜🎜 Wie in den Abbildungen 1 und 2 dargestellt Nachfolgend finden Sie den normalen Redis-Cluster-Cluster und den Redis-Cluster-Schlüsselzugriff mithilfe einer Proxy-Agent-Ebene. 🎜🎜
🎜🎜🎜🎜 Wie oben erwähnt, Hotkeys führen zu einem extrem hohen Lastdruck auf eine kleine Anzahl von Knoten im Cluster. Wenn sie nicht richtig gehandhabt werden, können diese Knoten ausfallen, was sich auf den Betrieb des gesamten Cache-Clusters auswirkt. Daher müssen wir Hotkeys rechtzeitig erkennen und lösen Sie sie. 🎜
1. Hotkey-Erkennung
🎜 Die Hotkey-Erkennung hat aufgrund der Streuung des Redis-Clusters und des Hotkeys einige erhebliche Auswirkungen und kann daher sorgfältig überlegt werden über den Prozess zur Entwicklung einer Lösung zur Erkennung von Hotspot-Schlüsseln. 🎜
1.1 QPS-Überwachung jedes Slots im Cluster
🎜 Die offensichtlichste Auswirkung von Hotkeys besteht darin, dass die QPS im gesamten Redis-Cluster überwacht werden Unter der Voraussetzung, dass der Verkehr ungleichmäßig auf die Slots im Cluster verteilt ist, können wir uns zunächst vorstellen, den Verkehr in jedem Slot zu überwachen, den Verkehr in jedem Slot zu vergleichen und ihn dann zu vergleichen Beim Erkennen der betroffenen Steckplätze wird ein Hotkey angezeigt. Obwohl diese Überwachung am bequemsten ist, ist die Granularität zu grob. Sie eignet sich nur für frühe Cluster-Überwachungslösungen und nicht für Szenarien, in denen Hotkeys genau erkannt werden. 🎜
1.2 Der Proxy-Mechanismus wird als gesamte Verkehrseingangsstatistik verwendet
🎜 Wenn wir den Redis-Cluster-Proxy-Modus in Abbildung 2 verwenden, Aufgrund von Alle Anforderungen werden zuerst an den Proxy und dann an den spezifischen Slot-Knoten weitergeleitet. Anschließend können die Erkennungsstatistiken dieses Hotkeys im Proxy erstellt werden, basierend auf dem
Zeitgleitfenster
. Zählen Sie jeden Schlüssel und dann die Schlüssel, die den entsprechenden Schwellenwert überschreiten. Um zu viele redundante Statistiken zu verhindern, können Sie auch einige Regeln festlegen, um nur Schlüssel zu zählen, die dem Präfix und Typ entsprechen. Diese Methode erfordert mindestens einen Proxy-Mechanismus und stellt Anforderungen an die Redis-Architektur. 🎜
1.3 Redis LFU-basierter Hotspot-Schlüsselerkennungsmechanismus
🎜 Versionen von Redis 4.0 oder höher unterstützen LFU-basierte Hotspots auf jedem Knoten Schlüsselerkennungsmechanismus: Verwenden Sie
redis-cli –hotkeys
. Fügen Sie die Option –hotkeys hinzu, wenn Sie redis-cli ausführen. Sie können diesen Befehl regelmäßig auf dem Knoten verwenden, um den entsprechenden Hotspot-Schlüssel zu ermitteln. 🎜🎜
🎜🎜 as Wie in der Abbildung gezeigt, können Sie die Ausführungsergebnisse von
redis-cli –hotkeys
und die statistischen Informationen zu Hotkeys sehen. Die Ausführungszeit dieses Befehls ist lang und Sie können eine geplante Ausführung einrichten um Statistiken zu sammeln. 🎜
1.4 Erkennung basierend auf dem Redis-Client
Da Redis-Befehle jedes Mal vom Client ausgegeben werden, können wir auf dieser Grundlage statistische Zählungen in einigen Codes des Redis-Clients durchführen, und jeder Client führt Statistiken basierend auf dem Zeitgleitfenster durch. Nach Überschreiten eines bestimmten Schwellenwerts wird es dem Server gemeldet, und der Server sendet es dann einheitlich an jeden Client und konfiguriert die entsprechende Ablaufzeit.
Diese Methode sieht schöner aus, ist jedoch in einigen Anwendungsszenarien tatsächlich nicht so geeignet, da die Änderung auf der Clientseite einen größeren Speicheraufwand für den laufenden Prozess mit sich bringt. Direkter sind Sprachen mit automatischer Speicherverwaltung, z Java und goLang erstellen häufiger Objekte, lösen GC aus und führen zu einer Verlängerung der Schnittstellenantwortzeit. Dies ist nicht leicht vorherzusagen. 优美
,其实在一些应用场景中并不是那么合适,因为在client端这一侧的改造,会给运行的进程带来更大的内存开销,更直接的来说,对于Java和goLang这种自动内存管理的语言,会更加频繁的创建对象,从而触发gc导致接口响应耗时增加的问题,这个反而是不太容易预料到的事情。
最终可以通过各个公司的基建,做出对应的选择。
2.热key解决
通过上述几种方式我们探测到了对应热key或者热slot,那么我们就要解决对应的热key问题。解决热key也有好几种思路可以参考,我们一个一个捋一下。
2.1 对特定key或slot做限流
一种最简单粗暴的方式,对于特定的slot或者热key做限流,这个方案明显对于业务来说是有损的,所以建议只用在出现线上问题,需要止损的时候进行特定的限流。
2.2 使用二级(本地)缓存
本地缓存也是一个最常用的解决方案,既然我们的一级缓存扛不住这么大的压力,就再加一个二级缓存吧。由于每个请求都是由service发出的,这个二级缓存加在service端是再合适不过了,因此可以在服务端每次获取到对应热key时,使用本地缓存存储一份,等本地缓存过期后再重新请求,降低redis集群压力。以java为例,guavaCache就是现成的工具。以下示例:
//本地缓存初始化以及构造
private static LoadingCache<String, List<Object>> configCache
= CacheBuilder.newBuilder()
.concurrencyLevel(8) //并发读写的级别,建议设置cpu核数
.expireAfterWrite(10, TimeUnit.SECONDS) //写入数据后多久过期
.initialCapacity(10) //初始化cache的容器大小
.maximumSize(10)//cache的容器最大
.recordStats()
// build方法中可以指定CacheLoader,在缓存不存在时通过CacheLoader的实现自动加载缓存
.build(new CacheLoader<String, List<Object>>() {
@Override
public List<Object> load(String hotKey) throws Exception {
}
});
//本地缓存获取
Object result = configCache.get(key);
本地缓存对于我们的最大的影响就是数据不一致的问题,我们设置多长的缓存过期时间,就会导致最长有多久的线上数据不一致问题,这个缓存时间需要衡量自身的集群压力以及业务接受的最大不一致时间。
2.3 拆key
如何既能保证不出现热key问题,又能尽量的保证数据一致性呢?拆key也是一个好的解决方案。
我们在放入缓存时就将对应业务的缓存key拆分成多个不同的key。如下图所示,我们首先在更新缓存的一侧,将key拆成N份,比如一个key名字叫做"good_100",那我们就可以把它拆成四份,"good_100_copy1"、"good_100_copy2"、"good_100_copy3"、"good_100_copy4",每次更新和新增时都需要去改动这N个key,这一步就是拆key。
对于service端来讲,我们就需要想办法尽量将自己访问的流量足够的均匀,如何给自己即将访问的热key上加入后缀。几种办法,根据本机的ip或mac地址做hash,之后的值与拆key的数量做取余,最终决定拼接成什么样的key后缀,从而打到哪台机器上;服务启动时的一个随机数对拆key的数量做取余。
2.4 本地缓存的另外一种思路 配置中心
对于熟悉微服务配置中心的伙伴来讲,我们的思路可以向配置中心的一致性转变一下。拿nacos来举例,它是如何做到分布式的配置一致性的,并且相应速度很快?那我们可以将缓存类比配置,这样去做。
长轮询
+本地化
Am Ende können Sie über die Infrastruktur jedes Unternehmens entsprechende Entscheidungen treffen. 🎜
2. Hotkey-Lösung
🎜 Nachdem wir mit den oben genannten Methoden den entsprechenden Hotkey oder Hot-Slot erkannt haben, müssen wir das entsprechende Hotkey-Problem lösen. Es gibt mehrere Ideen zum Lösen von Hotkeys. Gehen wir sie einzeln durch. 🎜
🎜2.1 Den Fluss bestimmter Tasten oder Slots begrenzen🎜🎜🎜 Der einfachste und einfachste Weg besteht darin, den Fluss bestimmter Slots oder Hotkeys zu begrenzen Geschäft Es ist verlustbehaftet, daher wird empfohlen, eine spezifische Strombegrenzung nur dann zu verwenden, wenn ein Online-Problem vorliegt und der Verlust gestoppt werden muss. 🎜🎜2.2 Second-Level-Cache (lokal) verwenden 🎜🎜🎜 Lokaler Cache ist auch die am häufigsten verwendete Lösung Da unser First-Level-Cache einem so starken Druck nicht standhalten kann Fügen Sie einen Cache der zweiten Ebene hinzu. Da jede Anforderung vom Dienst ausgegeben wird, ist es perfekt, diesen Cache der zweiten Ebene zur Dienstseite hinzuzufügen. Daher kann der Server jedes Mal, wenn er den entsprechenden Hotkey erhält, den lokalen Cache verwenden, um eine Kopie bis zum lokalen Cache zu speichern Läuft dann erneut ab, um den Druck auf den Redis-Cluster zu verringern. Am Beispiel von Java ist guavaCache ein vorgefertigtes Tool. Das folgende Beispiel: 🎜rrreee🎜 Die größte Auswirkung des lokalen Caches auf uns ist das Problem der Dateninkonsistenz. Wie lange wir die Cache-Ablaufzeit festlegen, führt zu dem längsten Online-Dateninkonsistenzproblem. Diese Cache-Zeit muss den eigenen Clusterdruck messen und die maximale vom Unternehmen akzeptierte inkonsistente Zeit. 🎜🎜2.3 Schlüsselentfernung🎜🎜🎜 Wie kann sichergestellt werden, dass keine Hotkey-Probleme auftreten und gleichzeitig die Datenkonsistenz so weit wie möglich sichergestellt wird? Auch das Abziehen des Schlüssels ist eine gute Lösung. 🎜🎜 Wenn wir es in den Cache legen, teilen wir den Cache-Schlüssel des entsprechenden Unternehmens in mehrere verschiedene Schlüssel auf. Wie in der Abbildung unten gezeigt, teilen wir den Schlüssel zunächst auf der Seite des Update-Cache in N Teile auf. Wenn ein Schlüssel beispielsweise „good_100“ heißt, können wir ihn in vier Teile aufteilen: „good_100_copy1“, „good_100_copy2“. „, „good_100_copy3“, „good_100_copy4“, diese N Schlüssel müssen jedes Mal geändert werden, wenn sie aktualisiert oder hinzugefügt werden. In diesem Schritt wird der Schlüssel entfernt. 🎜🎜 Auf der Serviceseite müssen wir Möglichkeiten finden, den Datenverkehr, auf den wir zugreifen, gleichmäßig zu gestalten und den Hotkeys, auf die wir zugreifen möchten, Suffixe hinzuzufügen. Es gibt mehrere Möglichkeiten, einen Hash basierend auf der IP- oder MAC-Adresse des Computers zu erstellen, dann den Restwert und die Anzahl der geteilten Schlüssel zu nehmen und schließlich zu entscheiden, in welche Art von Schlüsselsuffix er gespleißt wird. um anzugeben, auf welche Maschine es beim Start des Dienstes übertragen wird. Die Zufallszahl ist der Rest der Anzahl der geteilten Schlüssel. 🎜🎜🎜🎜2.4 Eine andere Denkweise über das lokale Cache-Konfigurationscenter🎜🎜🎜 Für diejenigen, die mit dem Microservice-Konfigurationscenter vertraut sind: Unsere Denkweise kann sich zur Konsistenz des Konfigurationscenters ändern. Nehmen Sie als Beispiel Nacos, wie wird eine verteilte Konfigurationskonsistenz erreicht und schnell reagiert? Dann können wir die Cache-Analogie mit der Konfiguration vergleichen und es so machen. 🎜🎜 Lange Abfrage
+ Lokalisierung
Konfiguration. Zuerst werden alle Konfigurationen initialisiert, wenn der Dienst gestartet wird, und dann wird regelmäßig eine lange Abfrage gestartet, um zu überprüfen, ob sich die aktuelle Dienstüberwachungskonfiguration geändert hat. Bei einer Änderung wird die lange Abfrageanforderung sofort zurückgegeben, um die lokale Konfiguration zu aktualisieren. Wenn es keine Änderung gibt, verwenden alle Geschäftscodes die lokale Speicher-Cache-Konfiguration. Dies stellt die Aktualität und Konsistenz der verteilten Cache-Konfiguration sicher. 🎜2.5 Andere Pläne, die im Voraus erstellt werden können
Jede der oben genannten Lösungen ist relativ unabhängig, um das Hotkey-Problem zu lösen. Wenn wir also wirklich mit geschäftlichen Anforderungen konfrontiert sind, haben wir tatsächlich lange Zeit, über das Gesamtlösungsdesign nachzudenken . Bei Hotkey-Problemen, die durch einige extreme Flash-Sales-Szenarien verursacht werden, können wir, wenn wir über genügend Budget verfügen, das Servicegeschäft und den Redis-Cache-Cluster direkt isolieren, um eine Beeinträchtigung des normalen Geschäfts zu vermeiden, und gleichzeitig vorübergehend eine bessere Notfallwiederherstellung einführen und Aktuelle Begrenzungsmaßnahmen.
Einige integrierte Lösungen
Es gibt bereits viele relativ vollständige Lösungen auf Anwendungsebene für HotKey. Darunter verfügt JD.com über ein Open-Source-Hotkey-Tool. Das Prinzip besteht darin, Einblicke in den Client zu gewinnen Seite und melden Sie dann den Antwort-Hotkey. Nachdem der Server ihn erkannt hat, sendet er den entsprechenden Hotkey zum lokalen Caching an den entsprechenden Server, und dieser lokale Cache wird synchron aktualisiert, nachdem der entsprechende Remote-Schlüssel aktualisiert wurde. Es ist bereits relativ ausgereift Derzeitige Lösung: 自动探测热key、分布式一致性缓存
JD Retail Hotkey.
Zusammenfassung
Im Folgenden finden Sie einige Lösungen zum Umgang mit Hotkeys, die der Autor grob verstanden oder geübt hat, von der Entdeckung von Hotkeys bis zur Lösung der beiden Schlüsselprobleme von Hotkeys. Jede Lösung hat Vor- und Nachteile, wie z. B. geschäftliche Inkonsistenzen, Schwierigkeiten bei der Implementierung usw. Sie können entsprechende Anpassungen und Änderungen basierend auf den aktuellen Merkmalen Ihres eigenen Unternehmens und der aktuellen Unternehmensinfrastruktur vornehmen.
Weitere Kenntnisse zum Thema Programmierung finden Sie unter:
Einführung in die Programmierung! !
Das obige ist der detaillierte Inhalt vonLassen Sie uns darüber sprechen, wie man mit dem Cache-Hotkey-Problem in Redis umgeht. Häufig verwendete Lösungsfreigabe. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!