Що таке Redis і навіщо використовують цей інструмент?

Що таке Redis і навіщо використовують цей інструмент?
Redis рано чи пізно з'являється майже в кожному вебпроєкті: як кеш, черга фонових задач, сховище сесій або лічильник у реальному часі. У світі Rails він довгий час був обов'язковим супутником Sidekiq і Action Cable. У цій статті розберемо, що таке Redis, як він працює, які структури даних пропонує, найпоширеніші сценарії використання з прикладами на Ruby та Rails, його обмеження, а також що змінилося з ліцензією Redis і в Rails 8.
Що таке Redis?
Redis (REmote DIctionary Server) — це сховище даних в оперативній пам'яті (in-memory). Він тримає дані в RAM і звертається до них за ключем, тому читання й запис відбуваються дуже швидко: типова операція триває помітно менше мілісекунди.
Redis створив Сальваторе Санфіліппо у 2009 році. Його часто називають key-value базою даних, але це применшення: Redis — це сервер структур даних. Значенням може бути не лише рядок, а й список, хеш, множина, відсортована множина, потік і багато іншого, а для кожного типу Redis надає атомарні команди.
Чому Redis такий швидкий?
- Дані живуть у пам'яті. Під час читання немає звернень до диска.
- Прості та ефективні структури даних, реалізовані мовою C.
- Однопотокове виконання команд. Команди виконуються по одній, тому всередині Redis немає блокувань і станів гонитви: кожна команда атомарна. Починаючи з Redis 6, мережеве введення-виведення може використовувати додаткові потоки, але самі команди досі виконуються послідовно.
- Легкий протокол (RESP) і підтримка конвеєрної обробки (pipelining), яка дозволяє клієнту надіслати багато команд за один мережевий обмін.
Основні типи даних
Тип Що це Типове застосування String Текст, число або бінарні дані до 512 МБ Кеш, лічильники, прапорці List Упорядкований список рядків Прості черги, останні елементи Hash Пари «поле–значення» всередині одного ключа Об'єкти, профілі користувачів, налаштування Set Унікальні невпорядковані значення Теги, унікальні відвідувачі, «хто вподобав» Sorted set Унікальні значення з вагою, відсортовані за вагою Рейтинги, таблиці лідерів, планування Stream Журнал подій, у який можна лише дописувати Event sourcing, обробка повідомлень Bitmap, HyperLogLog, Geo Спеціалізовані структури Прапорці активності, приблизний підрахунок унікальних, пошук поблизуУ Redis 8 до основного дистрибутива також увійшли JSON-документи, пошук і векторні множини, для яких раніше потрібні були окремі модулі.
Коротко про redis-cli
$ redis-cli
127.0.0.1:6379> SET greeting "Hello"
OK
127.0.0.1:6379> GET greeting
"Hello"
127.0.0.1:6379> SET session:abc123 "user_42" EX 3600 # спливає через 1 годину
OK
127.0.0.1:6379> TTL session:abc123
(integer) 3600
127.0.0.1:6379> INCR page:views
(integer) 1
127.0.0.1:6379> HSET user:42 name "Anna" city "Warsaw"
(integer) 2
127.0.0.1:6379> HGETALL user:42
1) "name"
2) "Anna"
3) "city"
4) "Warsaw"
Одна з найважливіших можливостей тут — TTL (time to live, час життя): будь-якому ключу можна задати термін дії, після якого Redis автоматично його видалить. Це саме те, що потрібно для кешу, сесій і тимчасових токенів.
Навіщо використовують Redis? Основні сценарії
У Ruby з Redis працюють через гем redis:
# Gemfile: gem "redis"
require "redis"
REDIS = Redis.new(url: ENV.fetch("REDIS_URL", "redis://localhost:6379/0"))
1. Кешування
Найпопулярніший сценарій. Важкі SQL-запити, результати звернень до зовнішніх API чи відрендерені фрагменти HTML зберігаються в Redis і під час наступного запиту повертаються миттєво. У Rails достатньо налаштувати сховище кешу:
# config/environments/production.rb
config.cache_store = :redis_cache_store, {
url: ENV.fetch("REDIS_URL", "redis://localhost:6379/1"),
expires_in: 1.day
}
# У будь-якому місці застосунку
def dashboard_stats
Rails.cache.fetch("dashboard/stats/#{Date.current}", expires_in: 10.minutes) do
{
users: User.count,
orders: Order.where(created_at: Date.current.all_day).count,
revenue: Order.paid.sum(:total)
}
end
end
Перший виклик виконує запити й зберігає результат, а наступні виклики протягом 10 хвилин читають його просто з Redis.
2. Черги фонових задач
Sidekiq, найпопулярніший обробник фонових задач для Ruby, зберігає свої черги в Redis. Надсилання листів, генерація звітів, обробка зображень — усе це виноситься з вебзапиту й виконується воркерами.
# app/sidekiq/welcome_email_job.rb
class WelcomeEmailJob
include Sidekiq::Job
sidekiq_options queue: :mailers, retry: 5
def perform(user_id)
user = User.find(user_id)
UserMailer.with(user: user).welcome.deliver_now
end
end
# У контролері або моделі
WelcomeEmailJob.perform_async(user.id)
3. Сесії та тимчасові дані
Зберігання сесій у Redis дозволяє кільком серверам застосунку спільно ними користуватися, а TTL автоматично видаляє старі сесії. Той самий підхід підходить для одноразових кодів, токенів скидання пароля та посилань підтвердження email.
4. Обмеження частоти запитів (rate limiting)
Атомарні лічильники з TTL дозволяють легко обмежити кількість запитів, наприклад 100 звернень до API на хвилину для одного користувача:
class RateLimiter
def initialize(redis: REDIS, limit: 100, period: 60)
@redis = redis
@limit = limit
@period = period
end
def allowed?(identifier)
window = Time.now.to_i / @period
key = "rate:#{identifier}:#{window}"
count, _ = @redis.multi do |tx|
tx.incr(key)
tx.expire(key, @period)
end
count <= @limit
end
end
limiter = RateLimiter.new
limiter.allowed?("user:42") # => true
Оскільки INCR атомарний, це коректно працює, навіть коли багато серверів застосунку одночасно звертаються до одного ключа. Починаючи з Rails 7.2 у контролерах є вбудований метод rate_limit, який під капотом використовує сховище кешу.
5. Реальний час і pub/sub
Redis підтримує модель «видавець–підписник»: один процес публікує повідомлення в канал, і всі підписники миттєво його отримують. Action Cable використовує це для доставки WebSocket-повідомлень між кількома серверами:
# config/cable.yml
production:
adapter: redis
url: <%= ENV.fetch("REDIS_URL", "redis://localhost:6379/2") %>
channel_prefix: myapp_production
6. Таблиці лідерів і рейтинги
Відсортовані множини зберігають елементи впорядкованими за вагою, тому топ-10 — це одна команда:
REDIS.zincrby("leaderboard", 50, "anna")
REDIS.zincrby("leaderboard", 30, "oleg")
REDIS.zincrby("leaderboard", 70, "maria")
REDIS.zrevrange("leaderboard", 0, 9, with_scores: true)
# => [["maria", 70.0], ["anna", 50.0], ["oleg", 30.0]]
REDIS.zrevrank("leaderboard", "anna") # => 1 (позиція, починаючи з 0)
7. Розподілені блокування
Коли задача не повинна виконуватися двічі одночасно на кількох серверах (наприклад, імпорт за розкладом), можна використати блокування на основі SET з опцією NX:
def with_lock(name, ttl: 30)
token = SecureRandom.uuid
acquired = REDIS.set("lock:#{name}", token, nx: true, ex: ttl)
return false unless acquired
begin
yield
ensure
# Видаляємо блокування, лише якщо воно досі наше
REDIS.eval(<<~LUA, keys: ["lock:#{name}"], argv: [token])
if redis.call("get", KEYS[1]) == ARGV[1] then
return redis.call("del", KEYS[1])
end
return 0
LUA
end
end
with_lock("daily_import") { DailyImport.run }
Персистентність: чи втрачає Redis дані після перезапуску?
Хоча Redis тримає дані в пам'яті, він уміє зберігати їх на диск:
- RDB (знімки): Redis періодично зберігає повний знімок даних. Компактно й швидко відновлюється, але зміни після останнього знімка можуть загубитися.
- AOF (append-only file): кожна команда запису дописується в журнал. Ризик втрати даних набагато менший (за замовчуванням не більше приблизно однієї секунди), але файл більший.
- Обидва разом: частий вибір, коли дані важливі.
- Без персистентності: підходить для чистого кешу, який можна створити заново.
Коли закінчується пам'ять: витіснення
Налаштування maxmemory обмежує обсяг RAM, який може використовувати Redis, а maxmemory-policy визначає, що відбувається при досягненні ліміту:
allkeys-lruабоallkeys-lfu— видаляти ключі, які найдовше не використовувалися або використовуються найрідше. Добрий вибір для кешу.noeviction— відмовляти в нових записах. Обов'язково для Sidekiq та інших черг, бо мовчки видалені задачі набагато гірші за помилку.
Тому в продакшені кеш і чергу задач часто тримають в окремих екземплярах Redis з різними налаштуваннями.
Встановлення Redis на Ubuntu
sudo apt update
sudo apt install redis-server
sudo systemctl enable --now redis-server
redis-cli ping # => PONG
Ключові рядки в /etc/redis/redis.conf:
bind 127.0.0.1 -::1 # слухати лише localhost
protected-mode yes
requirepass a-long-random-password # або використовуйте ACL-користувачів
maxmemory 512mb
maxmemory-policy allkeys-lru # для кешу; noeviction для Sidekiq
appendonly yes # увімкнути AOF, якщо дані важливі
Після зміни конфігурації перезапустіть сервіс: sudo systemctl restart redis-server.
Обмеження та підводні камені
- Оперативна пам'ять дорога й обмежена. Усі дані мають поміщатися в пам'ять, тому Redis не підходить для зберігання великих обсягів даних.
- Не заміна основній базі даних. Немає зв'язків, SQL і складних запитів, а гарантії збереження слабші, ніж у PostgreSQL чи MySQL. Redis доповнює базу даних, а не замінює її.
- Безпека. Ніколи не відкривайте порт 6379 в інтернет. Відкриті екземпляри Redis без пароля регулярно знаходять і атакують.
- Повільні команди блокують усіх. Оскільки команди виконуються по одній,
KEYS *на великій базі чи величезнийSMEMBERSзупинять усіх інших клієнтів. ВикористовуйтеSCANзамістьKEYS. - Інвалідація кешу. Кеш може повернути застарілі дані. Ретельно продумуйте TTL і момент очищення ключів.
Redis, ліцензії та Valkey
Багато років Redis поширювався під вільною ліцензією BSD. У 2024 році Redis Inc. перейшла на ліцензії з відкритим кодом, але не open source (RSALv2 і SSPL). У відповідь Linux Foundation і великі хмарні провайдери створили Valkey — повністю відкритий форк Redis 7.2, сумісний із клієнтами та командами Redis.
У 2025 році з виходом Redis 8 як один із варіантів додалася відкрита ліцензія AGPLv3. Сьогодні активно розвиваються і Redis, і Valkey. Для типового Rails-застосунку вибір рідко має значення: гем redis, Sidekiq і кеш Rails працюють з обома.
Чи потрібен Redis у Rails 8?
У Rails 8 з'явилася трійка «Solid», яка за замовчуванням використовує основну базу даних замість Redis:
- Solid Cache — кеш у таблиці бази даних (на диску, тому може бути набагато більшим за RAM).
- Solid Queue — фонові задачі для Active Job.
- Solid Cable — адаптер для Action Cable.
Це означає, що новий Rails-застосунок може працювати взагалі без Redis, що спрощує деплой на невеликий VPS. Redis досі чудовий вибір, коли вам потрібні:
- Sidekiq і його екосистема (можливості Pro/Enterprise, вебінтерфейс, безліч плагінів);
- мінімальні затримки для кешу й лічильників;
- відсортовані множини, потоки, pub/sub, атомарні лічильники, rate limiting і блокування;
- дуже високе навантаження з великою кількістю WebSocket-повідомлень у реальному часі.
Найкращі практики
- Завжди задавайте TTL для кешу й тимчасових даних.
- Використовуйте зрозумілі імена ключів із префіксами:
user:42:profile,rate:api:42. - Розділяйте кеш і черги між різними екземплярами або хоча б різними базами з відповідними політиками витіснення.
- Налаштуйте
maxmemory, щоб Redis не зайняв усю пам'ять сервера. - Захищайте Redis: слухайте лише localhost чи приватну мережу, задайте пароль або ACL, використовуйте TLS між серверами.
- Уникайте
KEYSі величезних значень; використовуйтеSCANі тримайте значення невеликими. - Моніторте:
INFO,SLOWLOG, використання пам'яті та відсоток влучань у кеш. - Не зберігайте єдину копію важливих даних у Redis. Джерелом істини має бути основна база даних.
Висновок
Redis — дуже швидке сховище даних у пам'яті з багатими структурами даних. Його використовують для кешування, черг фонових задач, сесій, обмеження частоти запитів, обміну повідомленнями в реальному часі, рейтингів і розподілених блокувань. Він не замінює реляційну базу даних, але бере на себе все, що має бути швидким, тимчасовим або спільним для кількох серверів. У Rails 8 можна почати без Redis завдяки Solid Cache, Solid Queue і Solid Cable, але зі зростанням навантаження та вимог Redis (або Valkey) залишається одним із найкорисніших інструментів веброзробника.
Назад



