← Назад к вопросам

Можно ли масштабировать Redis?

2.0 Middle🔥 181 комментариев
#Архитектура и паттерны#Базы данных (NoSQL)

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Можно ли масштабировать Redis

Да, Redis можно масштабировать, но с определёнными ограничениями и подходами. Redis — это in-memory база данных, и масштабирование требует понимания различных архитектурных паттернов.

1. Вертикальное масштабирование

Увеличение ресурсов одного сервера:

  • Больше RAM
  • Более мощный процессор
  • Лучшее сетевое оборудование
import redis

r = redis.Redis(host='localhost', port=6379)
info = r.info('memory')
print(f"Used memory: {info['used_memory_human']}")
print(f"Max memory: {info['maxmemory_human']}")

Конфигурация:

maxmemory 64gb
maxmemory-policy allkeys-lru

Ограничения:

  • Есть предел по памяти
  • SPOF (Single Point of Failure)
  • Один CPU не использует многоядерность

2. Горизонтальное масштабирование с Sharding

Разделение данных между несколькими серверами:

import hashlib
from redis import Redis
from redis.connection import ConnectionPool

class RedisShardingClient:
    def __init__(self, nodes: list[dict]):
        self.nodes = nodes
        self.connections = {}
        
        for i, node in enumerate(nodes):
            pool = ConnectionPool(
                host=node['host'],
                port=node['port'],
                decode_responses=True
            )
            self.connections[i] = Redis(connection_pool=pool)
    
    def _get_shard(self, key: str) -> int:
        hash_value = int(hashlib.md5(key.encode()).hexdigest(), 16)
        return hash_value % len(self.nodes)
    
    def set(self, key: str, value: str) -> bool:
        shard_id = self._get_shard(key)
        return self.connections[shard_id].set(key, value)
    
    def get(self, key: str) -> str:
        shard_id = self._get_shard(key)
        return self.connections[shard_id].get(key)

nodes = [
    {"host": "192.168.1.1", "port": 6379},
    {"host": "192.168.1.2", "port": 6379},
    {"host": "192.168.1.3", "port": 6379},
]

client = RedisShardingClient(nodes)
client.set("user:1:profile", "John Doe")
print(client.get("user:1:profile"))

3. Consistent Hashing

Вирtuальные ноды для минимизации переразмещения при добавлении/удалении серверов:

from sortedcontainers import SortedDict
import hashlib

class ConsistentHash:
    def __init__(self, nodes: list[str], virtual_nodes: int = 150):
        self.virtual_nodes = virtual_nodes
        self.ring = SortedDict()
        self.nodes = set()
        
        for node in nodes:
            self.add_node(node)
    
    def _hash(self, key: str) -> int:
        return int(hashlib.md5(key.encode()).hexdigest(), 16)
    
    def add_node(self, node: str) -> None:
        self.nodes.add(node)
        for i in range(self.virtual_nodes):
            virtual_key = f"{node}:{i}"
            hash_value = self._hash(virtual_key)
            self.ring[hash_value] = node
    
    def get_node(self, key: str) -> str:
        if not self.ring:
            return None
        
        hash_value = self._hash(key)
        idx = self.ring.bisect_right(hash_value)
        
        if idx == len(self.ring):
            idx = 0
        
        return list(self.ring.values())[idx]

ch = ConsistentHash(["server1", "server2", "server3"])
print(ch.get_node("user:1"))

4. Redis Cluster (встроенное решение)

Автоматическое управление sharding и replication:

Node1 Master --- Node4 Slave
Node2 Master --- Node5 Slave
Node3 Master --- Node6 Slave

Конфигурация:

port 6379
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000

Создание кластера:

redis-cli --cluster create \
  127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6381 \
  127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384 \
  --cluster-replicas 1

Использование:

from redis.cluster import RedisCluster

startup_nodes = [{"host": "127.0.0.1", "port": "6379"}]
rc = RedisCluster(startup_nodes=startup_nodes, decode_responses=True)

rc.set("foo", "bar")
print(rc.get("foo"))  # bar

5. Redis Replication для High Availability

Master-Slave архитектура:

master = redis.Redis(host="master.redis.com", port=6379)
master.set("data", "value")

slave = redis.Redis(host="slave.redis.com", port=6379)
slave.get("data")  # value

Конфигурация Slave:

slaveof master.redis.com 6379
slave-read-only yes

6. Redis Sentinel для автоматического Failover

Sentinel (мониторит мастер/слэйвы)
  |
  ├─ Master Redis
  └─ Slave Redis

Конфигурация:

port 26379
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel failover-timeout mymaster 180000

Использование:

from redis.sentinel import Sentinel

sentinels = [("127.0.0.1", 26379)]
sentinel = Sentinel(sentinels)

master = sentinel.master_for("mymaster")
master.set("key", "value")

slave = sentinel.slave_for("mymaster")
slave.get("key")

7. Рекомендации по масштабированию

СценарийПодход
Маленькое приложениеОдин Redis + Replication
Среднее приложениеRedis Cluster
Высокая нагрузка на чтениеReplication (читай с Slave)
ГеораспределённоеCluster + географическое разделение
Real-time и критичныеCluster + Sentinel + AOF

8. Балансировка нагрузки для чтения

import redis

class RedisLoadBalancer:
    def __init__(self, master_url: str, slave_urls: list[str]):
        self.master = redis.Redis.from_url(master_url)
        self.slaves = [redis.Redis.from_url(url) for url in slave_urls]
        self.current_slave_idx = 0
    
    def write(self, key: str, value: str) -> bool:
        return self.master.set(key, value)
    
    def read(self, key: str) -> str:
        slave = self.slaves[self.current_slave_idx]
        self.current_slave_idx = (self.current_slave_idx + 1) % len(self.slaves)
        return slave.get(key)

lb = RedisLoadBalancer(
    "redis://master:6379",
    ["redis://slave1:6379", "redis://slave2:6379"]
)

lb.write("user:1", "John")
print(lb.read("user:1"))  # John

Выводы

Redis масштабируется через:

  • Вертикальное — больше памяти на одном сервере
  • Sharding — разделение данных между серверами
  • Redis Cluster — встроенное решение
  • Replication — дублирование для HA
  • Sentinel — автоматический failover

Выбор метода зависит от требований приложения и критичности данных.

Можно ли масштабировать Redis? | PrepBro