Кэширование в C++: Redis и другие популярные инструменты
В высоконагруженных C++ приложениях скорость доступа к данным критична. Кэширование позволяет сократить время ответа сервера в 10–100 раз, снижая нагрузку на базы данных и внешние API. В этой статье мы разберём основные библиотеки для работы с кэшем на C++: от классического Redis до встраиваемых движков LevelDB и RocksDB.
1. Redis и клиентские библиотеки для C++
Redis — самый популярный in-memory key-value store, поддерживающий сложные структуры данных (списки, множества, хеши). Для C++ существует два основных клиента:
- hiredis — минималистичная C-библиотека (официальная), легко интегрируется в C++ через обёртки.
- redis-plus-plus — современная C++17 библиотека с полным покрытием команд Redis, поддержкой пула соединений, pipeline и транзакций.
Пример с hiredis (синхронный)
#include <hiredis/hiredis.h>
#include <iostream>
int main() {
redisContext *c = redisConnect("127.0.0.1", 6379);
if (c == nullptr || c->err) {
std::cerr << "Connection error: " << c->errstr << std::endl;
return 1;
}
redisReply *reply = (redisReply*)redisCommand(c, "SET key hello");
freeReplyObject(reply);
reply = (redisReply*)redisCommand(c, "GET key");
if (reply->type == REDIS_REPLY_STRING) {
std::cout << "GET key: " << reply->str << std::endl;
}
freeReplyObject(reply);
redisFree(c);
return 0;
}
Пример с redis-plus-plus (асинхронный + пул)
#include <sw/redis++/redis++.h>
#include <iostream>
int main() {
sw::redis::Redis redis("tcp://127.0.0.1:6379");
// Установка с TTL (5 секунд)
redis.setex("user:42", 5, "John Doe");
// Получение
auto val = redis.get("user:42");
if (val) {
std::cout << "Cached user: " << *val << std::endl;
} else {
std::cout << "Key expired or not found" << std::endl;
}
return 0;
}
Плюсы Redis: высокая скорость (микросекунды), богатый набор команд, репликация, кластеризация. Минусы: потребляет оперативную память, требует отдельного сервера.
2. Memcached и libmemcached
Memcached — простейший распределённый кэш, хранящий данные только в оперативной памяти. Для C++ используется библиотека libmemcached (или её C++ обёртка libmemcachedutil).
Пример с libmemcached
#include <libmemcached/memcached.h>
#include <iostream>
#include <cstring>
int main() {
memcached_st *memc = memcached_create(nullptr);
memcached_server_add(memc, "127.0.0.1", 11211);
const char *key = "session_token";
const char *value = "abc123";
memcached_return_t rc = memcached_set(memc, key, strlen(key),
value, strlen(value),
0, 0); // 0 - без сжатия, 0 - TTL
if (rc == MEMCACHED_SUCCESS) {
size_t value_length;
uint32_t flags;
char *result = memcached_get(memc, key, strlen(key),
&value_length, &flags, &rc);
if (rc == MEMCACHED_SUCCESS) {
std::cout << "Get: " << result << std::endl;
free(result);
}
}
memcached_free(memc);
return 0;
}
Когда выбирать Memcached: если нужно простое кэширование без сложных структур данных, и важна максимальная производительность. Redis выигрывает по функциональности, Memcached — по простоте.
3. Встраиваемые движки: LevelDB и RocksDB
Если кэш должен быть локальным (на диске) и не требовать сетевого сервера, идеальны LevelDB (Google) и RocksDB (Facebook). Они реализуют LSM-дерево и обеспечивают высокую скорость записи.
Пример с LevelDB
#include <leveldb/db.h>
#include <iostream>
int main() {