Caching in C++: Redis, Memcached und integrierte Lösungen

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Einleitung: Warum ist Caching in C++ notwendig?



In der modernen C++-Entwicklung ist die Geschwindigkeit einer Anwendung oft ein kritischer Faktor. Caching ermöglicht es, die Zugriffszeit auf Daten erheblich zu verkürzen, die Datenbanklast zu reduzieren und die Ausführung sich wiederholender Rechenoperationen zu beschleunigen. In diesem Artikel betrachten wir drei grundlegende Ansätze für Caching in C++ im Detail: die Verwendung externer Systeme (Redis und Memcached) sowie integrierte Lösungen, die "out of the box" verfügbar sind.



Unabhängig davon, ob Sie einen hochbelasteten Webserver, eine Spiel-Engine oder ein Finanzsystem entwickeln, kann die richtige Wahl der Caching-Strategie die Leistung um ein Vielfaches steigern. Wir analysieren die Vor- und Nachteile jedes Ansatzes und stellen fertige Codebeispiele für eine schnelle Integration bereit.



1. Integrierte Lösungen für Caching in C++



Bevor Sie externe Dienste anschließen, sollten Sie die Möglichkeiten in Betracht ziehen, die die Sprache C++ selbst und ihre Standardbibliothek bieten. Integrierte Lösungen eignen sich ideal für Single-Thread-Anwendungen oder Fälle, in denen Daten nicht zwischen mehreren Prozessen geteilt werden müssen.



1.1. Einfacher LRU-Cache basierend auf std::unordered_map



Der LRU-Algorithmus (Least Recently Used) ist einer der beliebtesten für integriertes Caching. Er entfernt automatisch die am wenigsten genutzten Elemente, wenn der Cache das Speicherlimit erreicht.



#include <unordered_map>#include <list>#include <mutex>

template <typename Key, typename Value>class LRUCache {private: size_t capacity_; std::list<Key> items_; std::unordered_map<Key, std::pair<Value, typename std::list<Key>::iterator>> cache_; std::mutex mutex_;

public: LRUCache(size_t capacity) : capacity_(capacity) {}

void put(const Key& key, const Value& value) { std::lock_guard<std::mutex> lock(mutex_); auto it = cache_.find(key); if (it != cache_.end()) { items_.erase(it->second.second); cache_.erase(it); } items_.push_front(key); cache_[key] = {value, items_.begin()}; if (cache_.size() > capacity_) { auto last = items_.back(); items_.pop_back(); cache_.erase(last); } }

std::optional<Value> get(const Key& key) { std::lock_guard<std::mutex> lock(mutex_); auto it = cache_.find(key); if (it == cache_.end()) return std::nullopt; // Verschiebt den Schlüssel an den Anfang der Liste items_.splice(items_.begin(), items_, it->second.second); return it->second.first; }};


Vorteile: minimaler Overhead, keine Netzwerkverzögerungen, vollständige Kontrolle über die Daten.

Nachteile: Daten werden nicht zwischen Threads geteilt (manuelle Synchronisation erforderlich), durch den Speicher eines einzelnen Prozesses begrenzt.



1.2. Verwendung von std::shared_mutex für Multithreading



Für Multithread-Anwendungen kann die Leistung durch die Verwendung von shared_mutex verbessert werden, das mehreren Threads gleichzeitiges Lesen ermöglicht:



#include <shared_mutex>

class ThreadSafeCache { std::map<std::string, std::string> data_; mutable std::shared_mutex mutex_; public: std::string read(const std::string& key) { std::shared_lock lock(mutex_); auto it = data_.find(key); return (it != data_.end()) ? it->second : ""; } void write(const std::string& key, const std::string& value) { std::unique_lock lock(mutex_); data_[key] = value; }};


2. Caching mit Memcached in C++



Memcached ist ein verteiltes In-Memory-Caching-System, das sich ideal zum Speichern kleiner Fragmente eignet.

Blogs

Buchempfehlungen