本文将使用 Docker 实现 Redis 常见的几种部署模式,包括单机模式、主从复制模式、哨兵模式、集群模式。 总结一下这几种模式的优缺点: | 部署模式 | 核心思想 | 优点 | 缺点 | 适用场景 | | :----------- | :---------------------- | :----------------------- | :-------------------------- | :------------------------------------- | | **单机模式** | 单个实例 | 简单、性能高 | 单点故障、容量有限 | 开发、测试、非核心缓存 | | **主从复制** | 一主多从,读写分离 | 数据备份、读扩展 | Master 单点、需手动故障转移 | 需要数据备份和高读吞吐量的场景 | | **哨兵模式** | 监控+主从,自动故障转移 | 自动故障转移、高可用 | 容量仍受限、配置较复杂 | 对可用性要求高,但数据量不大的场景 | | **集群模式** | 数据分片,去中心化 | 横向扩展、高可用、高吞吐 | 配置复杂、部分命令受限 | 海量数据、高并发、高可用的超大规模场景 | ## 单机模式 这是最简单的、最基础的部署方式,配置和维护比较简单,但是数据可靠性不高,适用于开发和测试环境,以及一些对可靠性要求不高的业务,能够容忍缓存数据丢失,可以轻易重建缓存。 **compose.yaml** 配置如下: ```yaml services: redis-standalone: image: redis:latest container_name: redis-standalone restart: unless-stopped ports: - 6379:6379/tcp volumes: - ./data:/data:rw - ./redis.conf:/usr/local/etc/redis/redis.conf:ro command: >- redis-server /usr/local/etc/redis/redis.conf ``` **redis.conf** 配置如下: ```conf bind 0.0.0.0 port 6379 requirepass xueye.io appendonly yes appendfilename "appendonly.aof" appendfsync everysec auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb aof-use-rdb-preamble yes save 900 1 save 300 10 save 60 10000 dbfilename dump.rdb rdbcompression yes maxmemory 512mb maxmemory-policy allkeys-lru ``` ## 主从模式 主从模式解决了单机模式的单点故障和数据备份的问题,包含一个主节点(Master)和多个从节点(Slave)。 写操作只在 Master 节点进行,Master 节点的数据会自动、异步地复制到所有 Slave 节点。Slave 节点通常是只读的,可以分担请求压力。 优点是 Master 宕机后,Slave 仍然可以提供读服务。Slave 作为 Master 节点的冗余备份,提高了数据安全性。 缺点是,Master 宕机后需要手动将一个 Slave 提升为新 Master。 主从模式适用于对写入性要求不高,能够接受手动故障转移的场景。 **compose.yaml** 配置如下: ```yaml services: redis-master: image: redis:latest container_name: redis-master command: redis-server /usr/local/etc/redis/redis.conf ports: - "6379:6379" volumes: - ./config/redis.conf:/usr/local/etc/redis/redis.conf - ./master/data:/data restart: always networks: - redis-net redis-slave-1: image: redis:latest container_name: redis-slave-1 command: redis-server /usr/local/etc/redis/redis.conf --replicaof redis-master 6379 ports: - "6380:6379" volumes: - ./config/redis.conf:/usr/local/etc/redis/redis.conf - ./slave1/data:/data restart: always depends_on: - redis-master networks: - redis-net redis-slave-2: image: redis:latest container_name: redis-slave-2 command: redis-server /usr/local/etc/redis/redis.conf --replicaof redis-master 6379 ports: - "6381:6379" volumes: - ./config/redis.conf:/usr/local/etc/redis/redis.conf - ./slave2/data:/data restart: always depends_on: - redis-master networks: - redis-net networks: redis-net: driver: bridge ``` **redis.conf** 配置如下: ```conf bind 0.0.0.0 port 6379 requirepass simaek.com masterauth simaek.com appendonly yes appendfsync everysec save 900 1 save 300 10 save 60 10000 replica-read-only yes ``` **验证主从关系:** ```shell docker-compose exec -it redis-master redis-cli ``` 进入`redis-cli`之后,进行认证并查看信息。 ``` 127.0.0.1:6379> AUTH simaek.com OK 127.0.0.1:6379> INFO replication # Replication role:master connected_slaves:2 slave0:ip=192.168.144.3,port=6379,state=online,offset=126,lag=1 slave1:ip=192.168.144.4,port=6379,state=online,offset=126,lag=1 master_failover_state:no-failover master_replid:099f05d52c796d1f1d52843b53402aa1e15a01c6 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:126 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:15 repl_backlog_histlen:112 ``` 可以尝试在 Master 和 Slave 读写数据进行进一步测试,这里就不展开了。 ## 哨兵模式 哨兵模式在主从模式的基础上,引入了“哨兵(Sentinel)”进程来监控整个 Redis 系统,实现了自动故障转移。 由一个或者多个 Sentinel 进程组成的集群,用于监控所有的 Master 和 Slave 节点。当 Sentinel 检测到 Master 节点宕机时,会自动在 Slave 节点中选举出一个新的 Master,然后更新其他 Slave 节点的配置,让它们复制新的 Master,并且通知客户端新的 Master 地址。 哨兵模式解决了主从模式的可用问题,但是性能上还是受限于 Master 单节点。 哨兵模式适用于要求可用性,但是数据量可以被单个 Redis 实例承载的场景。 沿用主从的配置,新增加额外的哨兵集群。 **compose.yaml** 配置如下: ```yaml services: # --snip-- sentinel-1: image: redis:latest container_name: sentinel-1 command: redis-server /usr/local/etc/redis/sentinel.conf --sentinel ports: - "26379:26379" volumes: - ./config/sentinel.conf:/usr/local/etc/redis/sentinel.conf restart: always depends_on: - redis-master - redis-slave-1 - redis-slave-2 networks: - redis-net sentinel-2: image: redis:latest container_name: sentinel-2 command: redis-server /usr/local/etc/redis/sentinel.conf --sentinel ports: - "26380:26379" volumes: - ./config/sentinel.conf:/usr/local/etc/redis/sentinel.conf restart: always depends_on: - redis-master - redis-slave-1 - redis-slave-2 networks: - redis-net sentinel-3: image: redis:latest container_name: sentinel-3 command: redis-server /usr/local/etc/redis/sentinel.conf --sentinel ports: - "26381:26379" volumes: - ./config/sentinel.conf:/usr/local/etc/redis/sentinel.conf restart: always depends_on: - redis-master - redis-slave-1 - redis-slave-2 networks: - redis-net ``` **sentinel.conf** 配置如下: ```conf # 哨兵默认监听端口 port 26379 sentinel resolve-hostnames yes # 告诉哨兵去监控哪个主节点 # 格式: sentinel monitor # : 主节点集群的逻辑名称,由你自定义,客户端会用它来发现主节点。 # : 主节点的地址。在 Docker Compose 中,我们使用服务名 redis-master。 # : 主节点的端口。 # : 法定人数。表示至少需要多少个哨兵同意,才能判定主节点下线并触发故障转移。 # 对于3个哨兵,设置为2是最佳实践 (N/2 + 1)。 sentinel monitor mymaster redis-master 6379 2 # 主节点被判定为下线前,需要多长时间无响应(毫秒) sentinel down-after-milliseconds mymaster 5000 # 故障转移超时时间(毫秒)。如果在这个时间内,从节点没有被提升为新主节点,则本次故障转移失败。 sentinel failover-timeout mymaster 60000 # 在故障转移后,一次可以有多少个从节点同时对新的主节点进行同步。 # 设置为1可以减少新主节点的压力。 sentinel parallel-syncs mymaster 1 # 由于我们的 Redis 节点设置了密码,哨兵必须使用此密码才能连接。 # 必须与上面的 monitor 指令中的名称一致。 sentinel auth-pass mymaster simaek.com ``` **连接到哨兵节点检查状态:** ```shell docker-compose exec -it sentinel-1 redis-cli -p 26379 127.0.0.1:26379> INFO sentinel # Sentinel sentinel_masters:1 sentinel_tilt:0 sentinel_tilt_since_seconds:-1 sentinel_total_tilt:0 sentinel_running_scripts:0 sentinel_scripts_queue_length:0 sentinel_simulate_failure_flags:0 master0:name=mymaster,status=ok,address=192.168.160.3:6379,slaves=2,sentinels=3 127.0.0.1:26379> SENTINEL get-master-addr-by-name mymaster 1) "192.168.160.3" 2) "6379" ``` 可以尝试模拟 Master 宕机,访问哨兵和选举出的新 Master 节点查看主从状态。此处不在赘述。 !> 这里有一个问题,在使用容器部署的时候,集群获取到的都是内部的地址。由于容器采用的 NAT 映射,在外部进行访问的时候,需要配置通告宿主机真实地址。 ## 集群模式 当数据量巨大,单个 Master 无法容纳时,就需要集群模式了。集群模式会将数据分散存储在多个 Master 节点上。Redis 集群预设为 16384 个哈希槽,每个 Key 经过 CRC16 算法计算后,分配到其中一个槽,每个 Master 节点负责一部分槽。 集群中每个节点都互相连接,知道其他节点负责哪些槽。客户端可以连接到任意一个节点,如果 Key 不在该节点,节点会被自动重定向到正确的节点。 另外每个 Master 节点都可以有自己的 Slave 节点,当某个 Master 宕机时,其对应的 Slave 会自动提升为新的 Master,接管其负责的哈希槽,保证集群的可用性。 集群模式的优点是可以通过增加节点来横向拓展容量和吞吐量,突破了单机内存限制。另外继承了类似哨兵模式的故障转移功能,不再需要引入哨兵来保证可用性。 但是集群模式也不是没有缺点,首先部署和维护相比其他模式都要复杂的多。对于跨多个 Slot 操作支持有限,除非这些 Key 恰好在同一个 Slot。Lua 脚本和事务也必须保证操作的 Key 在同一个节点上。 集群模式适用于海量数据的存储,数据量超过单机容量上限。需要高可用和高并发的场景也需要使用集群模式。 **compose.yaml** 配置如下: ```yaml services: redis-1: image: redis:latest container_name: redis-1 # 【关键】通告自己的主机名,并加载配置 command: redis-server /usr/local/etc/redis/redis.conf --cluster-announce-hostname redis-1 ports: - "7001:6379" - "17001:16379" # 集群总线端口 volumes: - ./config:/usr/local/etc/redis - ./data/node-1:/data restart: always networks: - redis-net redis-2: image: redis:latest container_name: redis-2 command: redis-server /usr/local/etc/redis/redis.conf --cluster-announce-hostname redis-2 ports: - "7002:6379" - "17002:16379" volumes: - ./config:/usr/local/etc/redis - ./data/node-2:/data restart: always networks: - redis-net redis-3: image: redis:latest container_name: redis-3 command: redis-server /usr/local/etc/redis/redis.conf --cluster-announce-hostname redis-3 ports: - "7003:6379" - "17003:16379" volumes: - ./config:/usr/local/etc/redis - ./data/node-3:/data restart: always networks: - redis-net redis-4: image: redis:latest container_name: redis-4 command: redis-server /usr/local/etc/redis/redis.conf --cluster-announce-hostname redis-4 ports: - "7004:6379" - "17004:16379" volumes: - ./config:/usr/local/etc/redis - ./data/node-4:/data restart: always networks: - redis-net redis-5: image: redis:latest container_name: redis-5 command: redis-server /usr/local/etc/redis/redis.conf --cluster-announce-hostname redis-5 ports: - "7005:6379" - "17005:16379" volumes: - ./config:/usr/local/etc/redis - ./data/node-5:/data restart: always networks: - redis-net redis-6: image: redis:latest container_name: redis-6 command: redis-server /usr/local/etc/redis/redis.conf --cluster-announce-hostname redis-6 ports: - "7006:6379" - "17006:16379" volumes: - ./config:/usr/local/etc/redis - ./data/node-6:/data restart: always networks: - redis-net networks: redis-net: driver: bridge ``` **redis.conf** 配置如下: ```conf bind 0.0.0.0 port 6379 # 【集群模式核心配置】 # 开启集群模式 cluster-enabled yes # 每个节点都有一个集群配置文件,由 Redis 自动维护,记录了集群中的其他节点等信息。 # 这个文件不能被多个节点共享,但因为我们为每个容器挂载了独立的数据目录,所以没问题。 cluster-config-file nodes.conf # 节点超时时间(毫秒) cluster-node-timeout 5000 # 【持久化与安全】 # 开启 AOF appendonly yes appendfsync everysec # 设置密码。所有节点密码必须相同。 requirepass simaek.com masterauth simaek.com ``` **创建集群:** 进入任何一个容器内执行。 ```shell docker-compose exec -it redis-1 redis-cli \ --cluster create \ redis-1:6379 \ redis-2:6379 \ redis-3:6379 \ redis-4:6379 \ redis-5:6379 \ redis-6:6379 \ --cluster-replicas 1 \ -a simaek.com ``` `--cluster-replicas 1` 意味着为每个创建的主节点分配 1 个从节点。因为我们有 6 个节点,所以它会自动创建 3 个主节点和 3 个从节点。 执行上述命令后,redis-cli 会计算出一个分片计划,并让你确认。 ``` **>>> Performing hash slots allocation on 6 nodes...** Master[0] -> Slots 0 - 5460 Master[1] -> Slots 5461 - 10922 Master[2] -> Slots 10923 - 16383 Adding replica redis-5:6379 to redis-1:6379 Adding replica redis-6:6379 to redis-2:6379 Adding replica redis-4:6379 to redis-3:6379 # --snip-- Can I set the cluster configuration? (type 'yes' to accept): ``` **连接集群验证**: 这里使用`-c`来连接开启集群模式(自动重定向),必须提供密码,否则重定向到其他节点时会没有权限。 ```shell docker-compose exec -it redis-1 redis-cli -c -a simaek.com 127.0.0.1:6379> CLUSTER INFO cluster_state:ok cluster_slots_assigned:16384 cluster_slots_ok:16384 cluster_slots_pfail:0 cluster_slots_fail:0 cluster_known_nodes:6 cluster_size:3 cluster_current_epoch:6 cluster_my_epoch:1 cluster_stats_messages_ping_sent:365 cluster_stats_messages_pong_sent:363 cluster_stats_messages_sent:728 cluster_stats_messages_ping_received:358 cluster_stats_messages_pong_received:365 cluster_stats_messages_meet_received:5 cluster_stats_messages_received:728 total_cluster_links_buffer_limit_exceeded:0 cluster_slot_migration_active_tasks:0 cluster_slot_migration_active_trim_running:0 cluster_slot_migration_active_trim_current_job_keys:0 cluster_slot_migration_active_trim_current_job_trimmed:0 cluster_slot_migration_stats_active_trim_started:0 cluster_slot_migration_stats_active_trim_completed:0s cluster_slot_migration_stats_active_trim_cancelled:0 ``` **测试数据分片和重定向:** ```shell 127.0.0.1:6379> set hello "redis" 127.0.0.1:6379> set other "simaek" -> Redirected to slot [11361] located at 192.168.176.4:6379 OK 192.168.176.4:6379> ``` Loading... 本文将使用 Docker 实现 Redis 常见的几种部署模式,包括单机模式、主从复制模式、哨兵模式、集群模式。 总结一下这几种模式的优缺点: | 部署模式 | 核心思想 | 优点 | 缺点 | 适用场景 | | :----------- | :---------------------- | :----------------------- | :-------------------------- | :------------------------------------- | | **单机模式** | 单个实例 | 简单、性能高 | 单点故障、容量有限 | 开发、测试、非核心缓存 | | **主从复制** | 一主多从,读写分离 | 数据备份、读扩展 | Master 单点、需手动故障转移 | 需要数据备份和高读吞吐量的场景 | | **哨兵模式** | 监控+主从,自动故障转移 | 自动故障转移、高可用 | 容量仍受限、配置较复杂 | 对可用性要求高,但数据量不大的场景 | | **集群模式** | 数据分片,去中心化 | 横向扩展、高可用、高吞吐 | 配置复杂、部分命令受限 | 海量数据、高并发、高可用的超大规模场景 | ## 单机模式 这是最简单的、最基础的部署方式,配置和维护比较简单,但是数据可靠性不高,适用于开发和测试环境,以及一些对可靠性要求不高的业务,能够容忍缓存数据丢失,可以轻易重建缓存。 **compose.yaml** 配置如下: ```yaml services: redis-standalone: image: redis:latest container_name: redis-standalone restart: unless-stopped ports: - 6379:6379/tcp volumes: - ./data:/data:rw - ./redis.conf:/usr/local/etc/redis/redis.conf:ro command: >- redis-server /usr/local/etc/redis/redis.conf ``` **redis.conf** 配置如下: ```conf bind 0.0.0.0 port 6379 requirepass xueye.io appendonly yes appendfilename "appendonly.aof" appendfsync everysec auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb aof-use-rdb-preamble yes save 900 1 save 300 10 save 60 10000 dbfilename dump.rdb rdbcompression yes maxmemory 512mb maxmemory-policy allkeys-lru ``` ## 主从模式 主从模式解决了单机模式的单点故障和数据备份的问题,包含一个主节点(Master)和多个从节点(Slave)。 写操作只在 Master 节点进行,Master 节点的数据会自动、异步地复制到所有 Slave 节点。Slave 节点通常是只读的,可以分担请求压力。 优点是 Master 宕机后,Slave 仍然可以提供读服务。Slave 作为 Master 节点的冗余备份,提高了数据安全性。 缺点是,Master 宕机后需要手动将一个 Slave 提升为新 Master。 主从模式适用于对写入性要求不高,能够接受手动故障转移的场景。 **compose.yaml** 配置如下: ```yaml services: redis-master: image: redis:latest container_name: redis-master command: redis-server /usr/local/etc/redis/redis.conf ports: - "6379:6379" volumes: - ./config/redis.conf:/usr/local/etc/redis/redis.conf - ./master/data:/data restart: always networks: - redis-net redis-slave-1: image: redis:latest container_name: redis-slave-1 command: redis-server /usr/local/etc/redis/redis.conf --replicaof redis-master 6379 ports: - "6380:6379" volumes: - ./config/redis.conf:/usr/local/etc/redis/redis.conf - ./slave1/data:/data restart: always depends_on: - redis-master networks: - redis-net redis-slave-2: image: redis:latest container_name: redis-slave-2 command: redis-server /usr/local/etc/redis/redis.conf --replicaof redis-master 6379 ports: - "6381:6379" volumes: - ./config/redis.conf:/usr/local/etc/redis/redis.conf - ./slave2/data:/data restart: always depends_on: - redis-master networks: - redis-net networks: redis-net: driver: bridge ``` **redis.conf** 配置如下: ```conf bind 0.0.0.0 port 6379 requirepass simaek.com masterauth simaek.com appendonly yes appendfsync everysec save 900 1 save 300 10 save 60 10000 replica-read-only yes ``` **验证主从关系:** ```shell docker-compose exec -it redis-master redis-cli ``` 进入`redis-cli`之后,进行认证并查看信息。 ``` 127.0.0.1:6379> AUTH simaek.com OK 127.0.0.1:6379> INFO replication # Replication role:master connected_slaves:2 slave0:ip=192.168.144.3,port=6379,state=online,offset=126,lag=1 slave1:ip=192.168.144.4,port=6379,state=online,offset=126,lag=1 master_failover_state:no-failover master_replid:099f05d52c796d1f1d52843b53402aa1e15a01c6 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:126 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:15 repl_backlog_histlen:112 ``` 可以尝试在 Master 和 Slave 读写数据进行进一步测试,这里就不展开了。 ## 哨兵模式 哨兵模式在主从模式的基础上,引入了“哨兵(Sentinel)”进程来监控整个 Redis 系统,实现了自动故障转移。 由一个或者多个 Sentinel 进程组成的集群,用于监控所有的 Master 和 Slave 节点。当 Sentinel 检测到 Master 节点宕机时,会自动在 Slave 节点中选举出一个新的 Master,然后更新其他 Slave 节点的配置,让它们复制新的 Master,并且通知客户端新的 Master 地址。 哨兵模式解决了主从模式的可用问题,但是性能上还是受限于 Master 单节点。 哨兵模式适用于要求可用性,但是数据量可以被单个 Redis 实例承载的场景。 沿用主从的配置,新增加额外的哨兵集群。 **compose.yaml** 配置如下: ```yaml services: # --snip-- sentinel-1: image: redis:latest container_name: sentinel-1 command: redis-server /usr/local/etc/redis/sentinel.conf --sentinel ports: - "26379:26379" volumes: - ./config/sentinel.conf:/usr/local/etc/redis/sentinel.conf restart: always depends_on: - redis-master - redis-slave-1 - redis-slave-2 networks: - redis-net sentinel-2: image: redis:latest container_name: sentinel-2 command: redis-server /usr/local/etc/redis/sentinel.conf --sentinel ports: - "26380:26379" volumes: - ./config/sentinel.conf:/usr/local/etc/redis/sentinel.conf restart: always depends_on: - redis-master - redis-slave-1 - redis-slave-2 networks: - redis-net sentinel-3: image: redis:latest container_name: sentinel-3 command: redis-server /usr/local/etc/redis/sentinel.conf --sentinel ports: - "26381:26379" volumes: - ./config/sentinel.conf:/usr/local/etc/redis/sentinel.conf restart: always depends_on: - redis-master - redis-slave-1 - redis-slave-2 networks: - redis-net ``` **sentinel.conf** 配置如下: ```conf # 哨兵默认监听端口 port 26379 sentinel resolve-hostnames yes # 告诉哨兵去监控哪个主节点 # 格式: sentinel monitor <master-group-name> <ip> <port> <quorum> # <master-group-name>: 主节点集群的逻辑名称,由你自定义,客户端会用它来发现主节点。 # <ip>: 主节点的地址。在 Docker Compose 中,我们使用服务名 redis-master。 # <port>: 主节点的端口。 # <quorum>: 法定人数。表示至少需要多少个哨兵同意,才能判定主节点下线并触发故障转移。 # 对于3个哨兵,设置为2是最佳实践 (N/2 + 1)。 sentinel monitor mymaster redis-master 6379 2 # 主节点被判定为下线前,需要多长时间无响应(毫秒) sentinel down-after-milliseconds mymaster 5000 # 故障转移超时时间(毫秒)。如果在这个时间内,从节点没有被提升为新主节点,则本次故障转移失败。 sentinel failover-timeout mymaster 60000 # 在故障转移后,一次可以有多少个从节点同时对新的主节点进行同步。 # 设置为1可以减少新主节点的压力。 sentinel parallel-syncs mymaster 1 # 由于我们的 Redis 节点设置了密码,哨兵必须使用此密码才能连接。 # <master-group-name> 必须与上面的 monitor 指令中的名称一致。 sentinel auth-pass mymaster simaek.com ``` **连接到哨兵节点检查状态:** ```shell docker-compose exec -it sentinel-1 redis-cli -p 26379 127.0.0.1:26379> INFO sentinel # Sentinel sentinel_masters:1 sentinel_tilt:0 sentinel_tilt_since_seconds:-1 sentinel_total_tilt:0 sentinel_running_scripts:0 sentinel_scripts_queue_length:0 sentinel_simulate_failure_flags:0 master0:name=mymaster,status=ok,address=192.168.160.3:6379,slaves=2,sentinels=3 127.0.0.1:26379> SENTINEL get-master-addr-by-name mymaster 1) "192.168.160.3" 2) "6379" ``` 可以尝试模拟 Master 宕机,访问哨兵和选举出的新 Master 节点查看主从状态。此处不在赘述。 !> 这里有一个问题,在使用容器部署的时候,集群获取到的都是内部的地址。由于容器采用的 NAT 映射,在外部进行访问的时候,需要配置通告宿主机真实地址。 ## 集群模式 当数据量巨大,单个 Master 无法容纳时,就需要集群模式了。集群模式会将数据分散存储在多个 Master 节点上。Redis 集群预设为 16384 个哈希槽,每个 Key 经过 CRC16 算法计算后,分配到其中一个槽,每个 Master 节点负责一部分槽。 集群中每个节点都互相连接,知道其他节点负责哪些槽。客户端可以连接到任意一个节点,如果 Key 不在该节点,节点会被自动重定向到正确的节点。 另外每个 Master 节点都可以有自己的 Slave 节点,当某个 Master 宕机时,其对应的 Slave 会自动提升为新的 Master,接管其负责的哈希槽,保证集群的可用性。 集群模式的优点是可以通过增加节点来横向拓展容量和吞吐量,突破了单机内存限制。另外继承了类似哨兵模式的故障转移功能,不再需要引入哨兵来保证可用性。 但是集群模式也不是没有缺点,首先部署和维护相比其他模式都要复杂的多。对于跨多个 Slot 操作支持有限,除非这些 Key 恰好在同一个 Slot。Lua 脚本和事务也必须保证操作的 Key 在同一个节点上。 集群模式适用于海量数据的存储,数据量超过单机容量上限。需要高可用和高并发的场景也需要使用集群模式。 **compose.yaml** 配置如下: ```yaml services: redis-1: image: redis:latest container_name: redis-1 # 【关键】通告自己的主机名,并加载配置 command: redis-server /usr/local/etc/redis/redis.conf --cluster-announce-hostname redis-1 ports: - "7001:6379" - "17001:16379" # 集群总线端口 volumes: - ./config:/usr/local/etc/redis - ./data/node-1:/data restart: always networks: - redis-net redis-2: image: redis:latest container_name: redis-2 command: redis-server /usr/local/etc/redis/redis.conf --cluster-announce-hostname redis-2 ports: - "7002:6379" - "17002:16379" volumes: - ./config:/usr/local/etc/redis - ./data/node-2:/data restart: always networks: - redis-net redis-3: image: redis:latest container_name: redis-3 command: redis-server /usr/local/etc/redis/redis.conf --cluster-announce-hostname redis-3 ports: - "7003:6379" - "17003:16379" volumes: - ./config:/usr/local/etc/redis - ./data/node-3:/data restart: always networks: - redis-net redis-4: image: redis:latest container_name: redis-4 command: redis-server /usr/local/etc/redis/redis.conf --cluster-announce-hostname redis-4 ports: - "7004:6379" - "17004:16379" volumes: - ./config:/usr/local/etc/redis - ./data/node-4:/data restart: always networks: - redis-net redis-5: image: redis:latest container_name: redis-5 command: redis-server /usr/local/etc/redis/redis.conf --cluster-announce-hostname redis-5 ports: - "7005:6379" - "17005:16379" volumes: - ./config:/usr/local/etc/redis - ./data/node-5:/data restart: always networks: - redis-net redis-6: image: redis:latest container_name: redis-6 command: redis-server /usr/local/etc/redis/redis.conf --cluster-announce-hostname redis-6 ports: - "7006:6379" - "17006:16379" volumes: - ./config:/usr/local/etc/redis - ./data/node-6:/data restart: always networks: - redis-net networks: redis-net: driver: bridge ``` **redis.conf** 配置如下: ```conf bind 0.0.0.0 port 6379 # 【集群模式核心配置】 # 开启集群模式 cluster-enabled yes # 每个节点都有一个集群配置文件,由 Redis 自动维护,记录了集群中的其他节点等信息。 # 这个文件不能被多个节点共享,但因为我们为每个容器挂载了独立的数据目录,所以没问题。 cluster-config-file nodes.conf # 节点超时时间(毫秒) cluster-node-timeout 5000 # 【持久化与安全】 # 开启 AOF appendonly yes appendfsync everysec # 设置密码。所有节点密码必须相同。 requirepass simaek.com masterauth simaek.com ``` **创建集群:** 进入任何一个容器内执行。 ```shell docker-compose exec -it redis-1 redis-cli \ --cluster create \ redis-1:6379 \ redis-2:6379 \ redis-3:6379 \ redis-4:6379 \ redis-5:6379 \ redis-6:6379 \ --cluster-replicas 1 \ -a simaek.com ``` `--cluster-replicas 1` 意味着为每个创建的主节点分配 1 个从节点。因为我们有 6 个节点,所以它会自动创建 3 个主节点和 3 个从节点。 执行上述命令后,redis-cli 会计算出一个分片计划,并让你确认。 ``` **>>> Performing hash slots allocation on 6 nodes...** Master[0] -> Slots 0 - 5460 Master[1] -> Slots 5461 - 10922 Master[2] -> Slots 10923 - 16383 Adding replica redis-5:6379 to redis-1:6379 Adding replica redis-6:6379 to redis-2:6379 Adding replica redis-4:6379 to redis-3:6379 # --snip-- Can I set the cluster configuration? (type 'yes' to accept): ``` **连接集群验证**: 这里使用`-c`来连接开启集群模式(自动重定向),必须提供密码,否则重定向到其他节点时会没有权限。 ```shell docker-compose exec -it redis-1 redis-cli -c -a simaek.com 127.0.0.1:6379> CLUSTER INFO cluster_state:ok cluster_slots_assigned:16384 cluster_slots_ok:16384 cluster_slots_pfail:0 cluster_slots_fail:0 cluster_known_nodes:6 cluster_size:3 cluster_current_epoch:6 cluster_my_epoch:1 cluster_stats_messages_ping_sent:365 cluster_stats_messages_pong_sent:363 cluster_stats_messages_sent:728 cluster_stats_messages_ping_received:358 cluster_stats_messages_pong_received:365 cluster_stats_messages_meet_received:5 cluster_stats_messages_received:728 total_cluster_links_buffer_limit_exceeded:0 cluster_slot_migration_active_tasks:0 cluster_slot_migration_active_trim_running:0 cluster_slot_migration_active_trim_current_job_keys:0 cluster_slot_migration_active_trim_current_job_trimmed:0 cluster_slot_migration_stats_active_trim_started:0 cluster_slot_migration_stats_active_trim_completed:0s cluster_slot_migration_stats_active_trim_cancelled:0 ``` **测试数据分片和重定向:** ```shell 127.0.0.1:6379> set hello "redis" 127.0.0.1:6379> set other "simaek" -> Redirected to slot [11361] located at 192.168.176.4:6379 OK 192.168.176.4:6379> ``` 最后修改:2025 年 12 月 25 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 如果觉得我的文章对你有用,请随意赞赏