各种模式
redis官方镜像
https://hub.docker.com/_/redis?tab=tags
配置选项
redis 配置文件为 redis.conf
protected-mode
在Redis的配置文件中,protected-mode 是一个安全相关的设置。当 protected-mode 设置为 yes(默认值)时,Redis 会采取一系列措施来防止外部未经授权的访问。这通常包括检查是否仅通过本地接口(如127.0.0.1)或者通过配置文件中明确指定的接口和端口来监听连接请求,以及是否需要密码验证。
如果将 protected-mode 设置为 no,Redis 将关闭这些额外的安全检查。这意味着,只要Redis服务器的端口(默认是6379)在防火墙或网络层面是对外开放的,任何能够访问该端口的客户端都可以连接到Redis服务器,而无需进行密码验证或满足特定的网络接口要求。
注意:
- 将
protected-mode设置为no会降低Redis服务器的安全性,因为它允许未经授权的访问。 - 在生产环境中,强烈建议保持
protected-mode为yes,并通过配置密码(requirepass配置项)和/或限制监听接口(bind配置项)来增强安全性。 - 如果你确实需要将
protected-mode设置为no(例如,在受信任的内部网络环境中),请确保其他安全措施(如防火墙规则、网络隔离等)已经到位,以防止未经授权的访问。
port
指定 redis 监听端口,例如:port 6379 表示指定 redis 监听端口为 6379
daemonize
在Redis的配置中,daemonize 是一个关键选项,用于控制Redis服务器是否以守护进程(Daemon)的方式运行。当设置为 no 时,具有特定的含义和影响:
一、含义
- 前台运行:当
daemonize设置为no时,Redis服务器将以前台进程的方式运行,而不是作为后台守护进程。这意味着Redis将占用启动它的终端,并在该终端中显示其输出和日志信息。
二、影响
- 交互性:
- 由于Redis在前台运行,它将占用启动它的终端。因此,一旦启动Redis,用户将无法在同一个终端中执行其他命令,直到手动停止Redis服务或关闭终端。
- 管理:
- 以非守护进程方式运行的Redis更容易直接监控和管理,因为所有的输出(包括日志和错误信息)都会直接显示在终端上。这有助于开发者和管理员快速发现和解决问题。
- 另一方面,由于Redis占用终端,可能需要编写脚本来自动化启动、停止和重启Redis服务。
- 自动化:
- 在自动化部署和管理场景中,通常更倾向于使用守护进程方式运行Redis(即
daemonize设置为yes),以便能够更容易地集成到脚本和监控系统中。
- 在自动化部署和管理场景中,通常更倾向于使用守护进程方式运行Redis(即
- 性能:
daemonize设置为no对Redis本身的性能影响较小。主要的影响在于Redis的运行方式,即是否占用终端。
三、使用场景
- 开发和调试环境:在开发和调试Redis应用时,通常希望Redis在前台运行,以便能够看到输出和错误信息。这有助于快速定位和解决问题。
- 临时测试:在进行临时测试或快速验证Redis功能时,也可以将
daemonize设置为no,以便快速启动和停止Redis服务。
四、配置方法
- 要设置
daemonize为no,可以编辑Redis的配置文件(通常是redis.conf),找到daemonize行,并将其值修改为no。然后,重新启动Redis服务以使更改生效。
综上所述,daemonize no 在Redis配置中用于控制Redis以前台进程的方式运行,这主要影响Redis的交互性、管理方式和自动化部署场景。在开发和调试环境中,这种设置可能很有用,但在生产环境中,通常更倾向于使用守护进程方式运行Redis。
pidfile
以 daemonize yes 模式运行 redis 时,redis pid 将被写入到 pidfile 指定的文件中,例如:pidfile /var/run/redis_6379.pid
logfile
在Redis的配置文件中,logfile 参数用于指定日志文件的路径和名称。如果 logfile 被设置为空字符串(""),这意味着Redis不会将日志信息写入到任何文件中。以下是对此设置的详细解释:
一、含义
- 无日志文件:当
logfile设置为空字符串时,Redis将不会生成日志文件。所有的日志信息将不会被持久化到磁盘上,而是可能通过标准输出(stdout)或标准错误(stderr)输出(这取决于Redis的运行方式和操作系统的配置)。
二、影响
- 日志记录:
- 由于没有指定日志文件,Redis将无法将重要的操作信息(如启动和关闭事件、配置更改、错误和警告信息、关键命令的执行状态等)记录到文件中。
- 这可能导致在故障排查和性能分析时缺乏必要的日志信息。
- 故障排查:
- 在没有日志文件的情况下,开发者和运维人员可能更难定位和解决问题。日志文件通常包含有关系统状态、错误和警告的详细信息,这些信息对于故障排查至关重要。
- 安全性:
- 在某些情况下,不记录日志可能被视为一种安全措施,因为它减少了潜在的敏感信息泄露的风险。然而,这也可能使得系统更难被监控和审计。
- 性能:
- 不记录日志可能会对Redis的性能产生轻微的影响(通常是正面的),因为避免了将日志信息写入磁盘的操作。然而,这种影响通常是非常小的,并且不太可能在大多数应用场景中显著改变Redis的性能。
三、配置方法
- 要更改
logfile的设置,可以编辑Redis的配置文件(通常是redis.conf),找到logfile行,并为其指定一个有效的路径和文件名。例如:
logfile /var/log/redis/redis-server.log- 确保Redis服务进程有权限写入指定的日志文件。如有必要,可以调整相应的权限。
- 重新启动Redis服务以使更改生效。
四、注意事项
- 在决定不记录日志之前,请仔细考虑其潜在的影响,并确保你了解这样做可能带来的风险。
- 如果你需要记录日志以便进行故障排查或性能分析,请确保
logfile参数被正确设置,并且Redis服务进程有权限写入指定的日志文件。
综上所述,将 logfile 设置为空字符串将导致Redis不记录任何日志信息。这可能会影响到故障排查、性能分析和系统监控等方面。因此,在配置Redis时,请仔细考虑是否需要记录日志,并相应地设置 logfile 参数。
cluster-enabled
在Redis的配置中,cluster-enabled 参数用于指定Redis节点是否以集群模式运行。当 cluster-enabled 设置为 yes 时,意味着该Redis节点将作为集群的一部分来运行。以下是对此设置的详细解释:
一、含义
- 集群模式:
cluster-enabled yes表示启用Redis的集群模式。在这种模式下,Redis节点将与其他节点协同工作,共同处理数据请求,以实现数据的高可用性和可扩展性。
二、影响
- 节点通信:
- 在集群模式下,Redis节点之间会通过内部通信机制(如Gossip协议)来交换状态信息、发现新节点、处理故障转移等。
- 这需要节点之间能够相互通信,通常是通过内部网络或局域网来实现的。
- 数据分片:
- Redis集群会将数据分成多个槽(slot),并将这些槽分布到不同的节点上。
- 当客户端请求数据时,集群会根据键的哈希值来确定它属于哪个槽,并将请求路由到负责该槽的节点上。
- 高可用性和故障转移:
- Redis集群提供了高可用性和故障转移机制。如果某个节点出现故障,集群中的其他节点将接管其负责的数据槽,并继续处理请求。
- 这需要集群中的节点能够感知到其他节点的状态变化,并自动进行故障转移。
- 配置和管理:
- 在集群模式下,Redis的配置和管理变得更加复杂。需要为每个节点指定集群配置文件、节点超时时间等参数。
- 此外,还需要使用Redis CLI或其他管理工具来管理集群(如添加或删除节点、查看集群状态等)。
三、配置方法
- 要启用Redis的集群模式,可以在Redis的配置文件(通常是
redis.conf)中找到cluster-enabled行,并将其值设置为yes。 - 同时,还需要配置其他与集群相关的参数,如
cluster-config-file(指定集群配置文件的路径和名称)、cluster-node-timeout(指定节点超时时间)等。 - 确保所有集群节点的配置文件都正确设置,并启动所有节点以形成集群。
四、注意事项
- 在启用集群模式之前,请确保你已经了解了Redis集群的基本原理和配置方法。
- 确保所有集群节点都能够相互通信,并且网络延迟和带宽足够支持集群的正常运行。
- 定期检查集群的状态和性能,以及时发现和解决问题。
综上所述,cluster-enabled yes 是启用Redis集群模式的关键配置。在配置和使用Redis集群时,请务必仔细考虑和设置相关参数,以确保集群的正常运行和高可用性。
单机版配置样板文件
https://gitee.com/dexterleslie/demonstration/blob/master/demo-redis/redis-server/docker-based/mode-standalone/redis.conf
启动选项
--replica-announce-ip 和 --replica-announce-port
https://baijiahao.baidu.com/s?id=1768636453217086050&wfr=spider&for=pc
--replica-announce-ip:指定 redis 节点间所有通信使用此ip地址
--replica-announce-port:指定 redis 节点间所有通信使用此端口
standalone模式(单机模式)
复制本站 示例 相关配置到本地
切换到mode-standalone目录内
cd mode-standalone启动 Redis6
修改 docker-compose.yml 内容如下:
services:
redis:
image: redis:6.2.6-bullseye
...
volumes:
- ./redis6.conf:/usr/local/etc/redis/redis.conf启动redis服务
docker compose up -d删除redis服务
docker compose down -v启动 Redis7
修改 docker-compose.yml 内容如下:
services:
redis:
image: redis:7.2.4
...
volumes:
- ./redis7.conf:/usr/local/etc/redis/redis.conf启动redis服务
docker compose up -d删除redis服务
docker compose down -vreplication模式(主从复制模式)
介绍
使用场景:读多写少的情况
主从复制,是指将一台 Redis 服务器的数据,复制到其他的 Redis 服务器。前者称为主节点(Master),后者称为从节点(Slave);数据的复制是单向的,只能由主节点到从节点。
默认情况下,每台 Redis 服务器都是主节点;且一个主节点可以有多个从节点 (或没有从节点),但一个从节点只能有一个主节点。
数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余。
负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务 (即写 Redis 数据时应用连接主节点,读 Redis 数据时应用连接从节点),分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。
主从同步原理
Redis Replication模式的主从同步原理是一种数据复制机制,用于将数据从一个主节点(Master)同步到一个或多个从节点(Slave)。这种机制旨在提高数据的可用性、读取性能和实现数据的冗余备份。以下是Redis Replication模式主从同步原理的详细解释:
一、主从节点角色与职责
- 主节点(Master):
- 负责处理写请求,并保存数据的最新状态。
- 在接收到写操作(如SET、DEL等)后,会将操作记录到本地,并同时将这些操作复制给从节点。
- 从节点(Slave):
- 复制主节点的数据,并保持与主节点数据的同步。
- 主要处理只读请求,分担主节点的读取压力。
二、同步过程
Redis的主从同步过程可以分为以下几个阶段:
- 建立连接:
- 从节点启动后,会发送一个SYNC或PSYNC命令给主节点,请求建立复制连接。
- 如果是首次建立连接,或者从节点没有主节点的数据(例如,从节点刚刚启动或数据被清空),则需要进行全量同步。
- 全量同步:
- 主节点在接收到SYNC或PSYNC命令后,会执行BGSAVE命令生成一个快照(RDB文件),并将快照发送给从节点。
- 同时,主节点会将生成快照以来的写操作记录到积压缓冲区(Replication Backlog)中。
- 从节点接收到快照后,会清空现有数据并加载快照。
- 加载完快照后,从节点会从积压缓冲区中接收并应用增量数据,以保持与主节点的数据同步。
- 增量同步:
- 在全量同步完成后,主节点和从节点就进入了增量同步阶段。
- 主节点会将每次写操作发送给从节点,从节点按顺序应用这些操作。
- Redis使用全局的复制偏移量(Replication Offset)来有效实现增量同步。每当主节点发送命令给从节点时,都会维护一个全局递增的复制偏移量,从节点也会跟踪自己当前同步的偏移量。
- 部分重同步:
- 如果在某些情况下,从节点与主节点短暂断联(例如,网络波动影响了连接),Redis会尝试实施部分重同步。
- Redis通过维护一个复制积压缓冲区来实现部分重同步。这个固定长度的循环缓冲区将存储最近的写命令。
- 若从节点在不久后重新连接,并且缺失的数据仍在缓冲区内,主节点就可以将缓冲区中的增量数据发送给从节点,从而完成同步,而无需进行全量同步。
三、心跳监控与故障恢复
- 心跳监控:
- 在保证主从节点连接状态和数据同步的健康方面,Redis引入了心跳机制。
- 从节点会定期向主节点发送心跳请求,以确认连接是否存活。
- 如果主节点在一段时间内没有收到从节点的心跳请求,会认为从节点出现故障,并可能会触发相应的故障恢复机制。
- 故障恢复:
- 当主节点出现故障时,可以使用Redis Sentinel或Redis Cluster等高级功能来实现自动故障转移。
- 在故障转移过程中,会选择一个从节点提升为新的主节点,并继续处理写请求和同步数据给其他从节点。
四、主从同步的优势与应用场景
- 读写分离:
- 将读请求分散到多个从节点上,减少主节点的负载,提高系统的读取性能。
- 高可用性:
- 当主节点故障时,可以将一个从节点提升为新的主节点,保证数据的高可用性。
- 数据备份与恢复:
- 从节点可以作为主节点的冗余备份,在主节点数据丢失或损坏时,可以使用从节点的数据进行恢复。
- 扩展性:
- 通过添加从节点,可以轻松地扩展Redis集群的读取能力。
Redis Replication模式的主从同步原理为数据的高可用性、读取性能优化和数据冗余备份提供了有力的支持。在实际应用中,可以根据具体需求和场景进行配置和优化,以实现最佳的性能和可靠性。
主从模式管理
示例会启动
demo-redis-replication-node1容器作为redis master节点,demo-redis-replication-node2、demo-redis-replication-node3、demo-redis-replication-node4容器作为redis slave节点。
docker-compose-add-slave-node.yml用于添加slave节点到现有的replication集群中。
注意:使用示例https://gitee.com/dexterleslie/demonstration/tree/master/demo-redis/redistemplate/redistemplate-replication测试主从模式。
复制https://gitee.com/dexterleslie/demonstration/tree/master/demo-redis/redis-server/docker-based/mode-replication相关配置到本地
启动主从模式
切换到mode-replication目录内
cd mode-replication启动redis服务
docker compose up -d查看redis master的replication状态,显示role: master
docker compose exec -it demo-redis-replication-node1 redis-cli info replication查看redis slave的replication状态,显示role: slave
docker compose exec -it demo-redis-replication-node2 redis-cli info replication添加redis slave到现有的主从集群中,下面命令执行后会启动一个名为demo-redis-replication-node-extra容器并自动加入到demo-redis-replication-node1主从集群中
docker compose -f docker-compose-add-slave-node.yml up -d从现有的主从集群中删除redis slave
docker compose -f docker-compose-add-slave-node.yml down -v主从切换
注意:此模式下只支持人工主从切换,人工主从切换后需要修改 spring-data-redis 配置指向到新 master 节点后重启应用。
redis 主从切换命令
https://blog.csdn.net/qq_36949713/article/details/106812171?app_version=6.1.9&csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22106812171%22%2C%22source%22%3A%22dexterchan%22%7D&utm_source=app
# 使用docker-compose启动上面的mode-replication主从模式
# 模拟master节点down机,NOTE: 此时集群支持读但不支持写
docker stop demo-redis-replication-node1
# 可以查看其中一个slave显示master是down状态
docker exec -it demo-redis-replication-node3 redis-cli info replication
# 切换 demo-redis-replication-node3 为master
docker exec -it demo-redis-replication-node3 redis-cli slaveof no one
# 持久化配置到redis.conf
docker exec -it demo-redis-replication-node3 redis-cli config rewrite
# 可以看到当前 demo-redis-replication-node3 已经切换为master,但还没有slave节点
docker exec -it demo-redis-replication-node3 redis-cli info replication
# 设置 demo-redis-replication-node2 指向新的master
docker exec -it demo-redis-replication-node2 redis-cli slaveof demo-redis-replication-node3 6379
docker exec -it demo-redis-replication-node2 redis-cli config rewrite
# 设置 demo-redis-replication-node4 指向新的master
docker exec -it demo-redis-replication-node4 redis-cli slaveof demo-redis-replication-node3 6379
docker exec -it demo-redis-replication-node4 redis-cli config rewrite
# 可以看到新的master下有3个slave节点了
docker exec -it demo-redis-replication-node3 redis-cli info replication
# 最后把应用配置 redistemplate/redistemplate-replication 修改新的master节点即可新增slave节点
新增节点后 redis 会自动通知 spring-data-redis 更新 slave 读取节点,新节点会参与到读负载均衡中。
# 启动redis replication模式
docker-compose up -d
# 启动完毕后新增节点
docker-compose -f docker-compose-add-slave-node.yaml up -d
# 此时可以使用 redistemplate/redistemplate-replication 调试删除slave节点
通过 docker stop 停止 slave 容器后,slave节点就能够自动从 master slave 节点列表中删除。
自动删除的 slave 节点不再参与 spring-data-redis 的读负载均衡。
自动删除的 slave 节点如果再次重新上线则又会重新参与到 spring-data-redis 的读负载均衡中。
slave 节点的删除和新增都不需要重启 spring-data-redis 应用就能够感知到 slave 的删除和新增。
# 停止容器表示删除节点
docker stop demo-redis-replication-node4
# 此时可以使用 https://gitee.com/dexterleslie/demonstration/tree/master/demo-redis/redistemplate/redistemplate-replication 调试sentinel模式(哨兵模式)
介绍
主从切换技术的方法是:当服务器宕机后,需要手动一台从机切换为主机,这需要人工干预,不仅费时费力,而且还会造成一段时间内服务不可用。为了解决主从复制的缺点,就有了哨兵模式。
哨兵(sentinel):是一个分布式系统,用于对主从结构中的每台服务器进行监控,当出现故障时通过投票机制选择新的 Master 并将所有 Slave 连接到新的 Master。所以整个运行哨兵的集群的数量不得少于3个节点。
哨兵模式的作用
- 监控:哨兵会不断地检查主节点和从节点是否运作正常。
- 自动故障转移:当主节点不能正常工作时,哨兵会开始自动故障转移操作,它会将失效主节点的其中一个从节点升级为新的主节点,并让其他从节点改为复制新的主节点。
- 通知(提醒):哨兵可以将故障转移的结果发送给客户端。
哨兵模式的结构由两部分组成,哨兵节点和数据节点:
- 哨兵节点:哨兵系统由一个或多个哨兵节点组成,哨兵节点是特殊的redis节点,不存储数据。
- 数据节点:主节点和从节点都是数据节点。
哨兵模式管理
启动哨兵模式
docker-compose-add-slave-node.yml用于添加slave节点到现有的集群中。
注意:使用示例https://gitee.com/dexterleslie/demonstration/tree/master/demo-redis/redistemplate/redistemplate-sentinel测试哨兵模式。
复制https://gitee.com/dexterleslie/demonstration/tree/master/demo-redis/redis-server/docker-based/mode-sentinel相关配置到本地
切换到mode-sentinel目录内
cd mode-sentinel编辑.env文件填写主机ip地址,.env内容如下:
# 宿主机ip
varHostIp=192.168.1.181启动redis sentinel服务
docker compose up -d查看sentinel相关状态包括redis master节点的信息
docker compose exec -it demo-redis-sentinel-node1 redis-cli -p 26379 info sentinel删除redis sentinel服务
docker compose down -v模拟 master 节点 down(删除节点)
master 节点 down 后大约过了 30s,sentinel 重新选举一个新的 master 节点。spring-data-redis 会被通知新的 master 节点和 slave 读节点不需要重启应用。
# 关闭master节点,大约等待30秒左右,sentinel会从slave节点中选举一个节点作为新的master
docker stop demo-redis-sentinel-repl-node1
# redistemplate/redistemplate-sentinel会被通知新的master节点,不需要重启应用
# 关闭master节点后,查看各个节点的replication信息被sentinel更新了
docker exec -it demo-redis-sentinel-repl-node2 redis-cli info replication
docker exec -it demo-redis-sentinel-repl-node3 redis-cli info replication
docker exec -it demo-redis-sentinel-repl-node4 redis-cli info replication
# 查看sentinel master节点sentinel信息
docker exec -it demo-redis-sentinel-node1 redis-cli -p 26379 info sentinel模拟 slave 节点 down(删除节点)
slave 节点 down 后,spring-data-redis 会被通知删除 slave 读节点不需要重启应用。
# 关闭 demo-redis-sentinel-repl-node3 slave节点
docker stop demo-redis-sentinel-repl-node3新增 slave 节点
slave 节点新增后,spring-data-redis 会被通知新增 slave 读节点不需要重启应用。
# 新增slave节点
docker-compose -f docker-compose-add-slave-node.yml up -dcluster模式(集群模式)
介绍
Redis分片集群(Redis Cluster)是一种分布式部署模式,它将数据划分为多个片(Shard),分别存储在不同的Redis节点上。以下是关于Redis分片集群的详细介绍:
一、架构与组成
- 多个节点:Redis分片集群由多个Redis节点组成,每个节点仅存储整个数据集的一部分。
- 数据分片:通过分片技术,Redis集群实现了数据的水平扩展。每个节点负责存储一部分数据,从而提高了整个集群的存储能力。
- 主从结构:在Redis分片集群中,每个主节点可以有多个从节点。从节点用于数据备份和故障恢复,提高了集群的高可用性。
二、工作原理
- 哈希槽分配:Redis集群引入了哈希槽的概念,整个集群有16384个哈希槽。每个key通过CRC16校验后对16384取模来决定放置在哪个槽中,集群的每个节点负责一部分哈希槽。
- 客户端请求转发:客户端请求可以访问集群中的任意节点,Redis会根据key的哈希值计算出对应的哈希槽,然后将请求转发到负责该哈希槽的节点上。
- 节点间协同工作:节点之间通过ping监测彼此的健康状态,确保集群的稳定性和可靠性。
三、常见操作
- 查看集群信息:使用redis-cli命令查看集群节点状态,例如
redis-cli -c -p 7000 cluster nodes。 - 添加新节点:当集群需要扩展时,可以添加新节点。添加新节点后,需要重新分配哈希槽,以确保数据的均匀分布。可以使用
redis-cli --cluster add-node命令添加新节点,并使用redis-cli --cluster reshard命令重新分配哈希槽。 - 故障恢复:当集群中的某个节点出现故障时,其从节点会接管其工作,确保数据的可用性和服务的连续性。
四、优势与应用场景
- 高可用性和可扩展性:Redis分片集群通过数据分片实现了高可用性和可扩展性,能够应对高并发和海量数据存储的需求。
- 负载均衡:由于数据被分散存储在多个节点上,因此可以实现负载均衡,提高整个集群的性能。
- 容灾备份:每个主节点都有多个从节点进行数据备份,当主节点出现故障时,从节点可以迅速接管工作,确保数据的完整性和服务的连续性。
Redis分片集群适用于需要处理大量数据和高并发请求的场景,如社交媒体、电商、金融等领域。通过合理的规划和配置,Redis分片集群可以稳定、高效地支持分布式系统,为实现更高性能和稳定性提供强有力的支持。
插槽的原理
Redis集群插槽原理是Redis集群实现数据分片、负载均衡和高可用性的关键机制。以下是关于Redis集群插槽原理的详细解释:
一、插槽的概念与数量
- 插槽定义:Redis集群将整个数据空间划分为16384个插槽(slots),每个插槽存储一部分数据。
- 插槽数量选择:16384个插槽是Redis集群设计中的一个权衡结果。较大的插槽数量可以提供更细的数据分片,但会增加集群元数据的大小和管理的复杂度。而16384既提供了足够的精度来进行分片和负载均衡,又确保了集群的可维护性。此外,16384是2的14次幂,便于利用位操作来提高哈希计算的效率。
二、插槽的分配与管理
- 插槽分配:Redis集群中的每个节点负责维护一部分插槽,即每个节点都负责管理一部分数据。集群通过CRC16哈希算法来计算每个key的哈希值,并对16384取模以确定该key应该存储在哪个插槽上。
- 客户端定位:当客户端连接到Redis集群时,会获取并缓存插槽的配置信息。这样,客户端可以快速地定位到存储某个key的目标节点,提高了数据定位的效率。
- 动态调整:当集群中的节点数量发生变化时,插槽及其数据可以在节点间按照既定的规则进行迁移,以确保数据的一致性和负载均衡。这种动态调整机制使得Redis集群能够灵活地应对节点的增减。
三、插槽与节点间的通信
- Gossip协议:Redis集群节点间使用Gossip协议进行通信,以维护集群的元数据。Gossip协议是一种去中心化的协议,允许节点之间互相交流状态信息。这有助于集群中的节点保持同步,并及时发现和处理节点的故障。
- 心跳消息:每个节点定期向其他节点发送心跳消息(如ping消息),包含自身状态和部分元数据。收到心跳消息的节点会回复pong消息,确认接收到消息并返回自身状态。这有助于监控节点的健康状态,并及时发现和处理潜在的故障。
四、插槽与故障恢复
- 故障检测:当集群中的某个节点出现故障时,其从节点会检测到主节点的FAIL状态,并尝试进行故障转移。故障转移过程中,从节点会收集其他主节点的选票,如果获得超过半数的支持,则成为新的主节点。
- 数据一致性:为确保数据的一致性,Redis集群提供了配置参数
min-replicas-to-write,要求写操作必须同步到至少一个从节点才能成功执行。这在一定程度上减少了数据丢失的风险。
五、插槽与客户端重定向
- 重定向机制:当客户端向错误的节点发送请求时,错误节点会返回一个MOVED响应,指示客户端前往正确的节点处理该请求。这个响应包含目标节点的地址,客户端收到跳转指令后,会更新本地的插槽映射表,以便下次请求直接发送到正确的节点。
- 高效性:这种跳转重定位机制能够动态调整客户端的插槽信息,减少错误请求带来的开销,提高请求处理的效率。
综上所述,Redis集群插槽原理是Redis集群实现数据分片、负载均衡和高可用性的基础。通过合理的插槽分配与管理、节点间的通信与协作、故障恢复机制以及客户端重定向机制,Redis集群能够稳定、高效地支持分布式系统。
迁移指定的插槽
Redis集群迁移指定的插槽是一个涉及多个步骤的过程,以下是一个详细的指南:
一、准备工作
- 检查集群状态:
- 使用
redis-cli -c -h <host> -p <port> cluster info命令检查集群的整体状态,确保集群处于健康状态。 - 验证所有节点是否正常运行,没有出现故障或不一致的情况。
- 使用
- 备份数据:
- 在迁移之前,务必对源节点上的数据进行备份。
- 可以使用RDB(Redis Database)或AOF(Append Only File)方式进行备份。
二、迁移插槽
- 连接源节点:
- 使用
redis-cli -h <source-node-ip> -p <source-node-port>命令连接到源节点。
- 使用
- 标记插槽为迁移状态:
- 使用
CLUSTER SETSLOT <slot> MIGRATING <target-node-id>命令将指定的插槽标记为迁移状态,并指定目标节点的ID。 - 例如,要迁移插槽1000,可以使用命令
redis-cli -h <source-node-ip> -p <source-node-port> CLUSTER SETSLOT 1000 MIGRATING <target-node-id>。
- 使用
- 执行迁移:
- 使用
CLUSTER MIGRATE <destination-node-ip> <destination-node-port> <slot> <timeout>命令将数据从源节点迁移到目标节点。 - 例如,要将插槽1000迁移到目标节点,可以使用命令
redis-cli -h <source-node-ip> -p <source-node-port> CLUSTER MIGRATE <destination-node-ip> <destination-node-port> 1000 <timeout>。 <timeout>参数指定迁移操作的超时时间(以毫秒为单位)。
- 使用
- 目标节点接收迁移:
- 在目标节点上,使用
CLUSTER SETSLOT <slot> IMPORTING <source-node-id>命令将插槽标记为导入状态,并指定源节点的ID。 - 例如,要在目标节点上接收插槽1000,可以使用命令
redis-cli -h <destination-node-ip> -p <destination-node-port> CLUSTER SETSLOT 1000 IMPORTING <source-node-id>。
- 在目标节点上,使用
三、确认迁移完成
- 源节点确认移除插槽:
- 一旦数据迁移完成,源节点需要确认迁移结果,并使用
CLUSTER SETSLOT <slot> NODE <target-node-id>命令将插槽的所有权转移到目标节点。 - 例如,要确认插槽1000的迁移结果,并使用命令
redis-cli -h <source-node-ip> -p <source-node-port> CLUSTER SETSLOT 1000 NODE <target-node-id>。
- 一旦数据迁移完成,源节点需要确认迁移结果,并使用
- 目标节点确认迁移完成:
- 在目标节点上,使用相同的命令
CLUSTER SETSLOT <slot> NODE <target-node-id>确认迁移完成,并激活插槽。
- 在目标节点上,使用相同的命令
四、验证迁移结果
- 验证目标节点上是否成功导入了插槽的数据。
- 使用
redis-cli -c -h <host> -p <port> cluster slots命令检查集群的插槽映射信息,确保迁移的插槽已正确分配给目标节点。
五、注意事项
- 迁移插槽可能会对Redis集群的性能产生影响,因此应合理安排迁移的时间和速度。
- 在迁移过程中,应持续监控集群的状态和性能,以确保迁移的顺利进行。
- 如果迁移过程中出现任何问题,应立即停止迁移并恢复备份数据。
通过以上步骤,您可以成功地将Redis集群中的指定插槽迁移到目标节点。请务必在迁移之前进行充分的准备工作,并在迁移过程中持续监控集群的状态和性能。
基于docker compose集群
使用
docker compose建立redis clusterhttps://blog.yowko.com/docker-compose-redis-cluster/
复制https://gitee.com/dexterleslie/demonstration/tree/master/demo-redis/redis-server/docker-based/mode-cluster示例到本地
启动redis cluster服务
# 基于redis6的集群
docker compose up -d
# 基于redis7的集群
# 注意:经过多次测试重启集群后容器ip地址变动也不会影响集群ok状态。
docker compose -f docker-compose-redis7.yml up -d查看集群状态信息
# 基于 redis6 集群
docker compose exec -it node1 redis-cli -p 6380 cluster info
# 基于 redis7 集群
docker compose -f docker-compose-redis7.yml exec -it node1 redis-cli -p 6380 cluster info查看集群节点信息
# 基于 redis6 集群
docker compose exec -it node1 redis-cli -p 6380 cluster nodes
# 基于 redis7 集群
docker compose -f docker-compose-redis7.yml exec -it node1 redis-cli -p 6380 cluster nodes删除redis cluster服务
# 基于 redis6 集群
docker compose down -v
# 基于 redis7 集群
docker compose -f docker-compose-redis7.yml down -v基于docker swarm集群
注意:在使用
docker swarm运行redis集群并且没有使用nfs存储时,需要绑定redis节点到指定的swarm节点中,否则在集群重启后会导致集群down。在使用nfs存储时则理论上不需要绑定redis节点到swarm节点中(未做实验)。
注意:通过docker stack rm test1删除redis集群后,需要手动在每个swarm节点上删除redis节点数据卷(命令docker volume rm $(docker volume ls | grep cluster-node | awk '{print $2}')),否则在下次创建集群时会报告错误导致无法创建新的redis集群。
复制https://gitee.com/dexterleslie/demonstration/tree/master/demo-redis/redis-server/docker-based/mode-cluster示例到本地,其中docker-stack.yml文件是redis集群在docker swarm部署的核心配置。
在swarm管理节点上执行以下命令部署redis集群
docker stack deploy test1 -c docker-stack.yaml在swarm管理节点上查看redis集群状态
docker exec -it `docker ps |grep node1 | awk '{print $1}'` redis-cli -c cluster info
docker exec -it `docker ps |grep node1 | awk '{print $1}'` redis-cli -c cluster nodes测试swarm中的redis集群是否丢失数据
# 生成数据
for i in {1..15}; do docker exec -it `docker ps|grep node1|awk '{print $1}'` redis-cli -c set key$i value$i; done
# 删除service模拟节点失败
docker service rm test1_node1
docker service rm test1_node3
docker service rm test1_node5
# 重建集群
docker stack deploy test1 -c docker-stack.yaml
# 执行以下命令依然能够读取redis集群中的数据,表示redis集群数据不丢失
for i in {1..15}; do v_val=$(docker exec -it $(docker ps|grep node2|awk '{print $1}') redis-cli -c get key$i); echo key$i=$v_val; done或者可以通过示例https://gitee.com/dexterleslie/demonstration/blob/master/spring-cloud/demo-spring-cloud-assistant/deployer/docker-stack.yaml测试swarm中的redis集群是否会丢失数据。
基于k8s集群
参考资料
参考以下资料基于k8s运行各种模式的redis
https://github.com/bitnami/charts/tree/main/bitnami/redis-clusterhttps://github.com/bitnami/charts/tree/main/bitnami/redishttps://github.com/bitnami/containers/tree/main/bitnami/redis-clusterhttps://github.com/bitnami/containers/tree/main/bitnami/redis
运行redis cluser模式
注意:为了实现
redis-cluster-0等待其他所有节点准备好并执行redis-cli --cluster create逻辑,需要借助helm生成REDIS_NODES(格式:redis-cluster-0:6379 redis-cluster-1:6379 redis-cluster-2:6379)。所以暂时放弃自动创建redis cluster方法转而使用人工介入的方式创建redis cluster。注意:使用
k8s运行redis7(redis7在初始化集群时支持不使用节点ip)集群,使用--cluster-announce-ip参数指定redis节点的无头服务名称,即使k8s节点重启后redis节点ip地址变化也不会导致redis集群失败。
下载redis cluster配置到本地,链接https://gitee.com/dexterleslie/demonstration/tree/master/demo-redis/redis-server/kubernetes-based/mode-cluster
给redis集群性能测试专用节点加污点和标签
注意:在性能测试时,避免
jmeter slave和redis集群在同一个k8s节点上运行导致相互干扰,所以需要给redis集群专用节点添加污点,标签是用于redis集群定向调度到指定k8s节点中。
kubectl taint node k8s-node-openresty support-only-perf-target:NoSchedule
kubectl label node k8s-node-openresty support-only-perf-target=创建并启动所有redis cluster节点
./create-k8s.sh查看redis statefulset是否已经启动
kubectl get statefulset等待所有redis cluster节点running状态后手动创建redis集群
https://medium.com/geekculture/redis-cluster-on-kubernetes-c9839f1c14b6
# 注意:最新版本redis集群创建可以通过下面的 <pod-name>.<headless-service> 方式创建,不需要使用ip地址
export REDIS_NODES=$(kubectl get pods -l app.kubernetes.io/name=redis-cluster -o json | jq -r '.items | map(.status.podIP) | join(":6379 ")'):6379
kubectl exec -it redis-cluster-0 -- redis-cli --cluster create --cluster-replicas 1 ${REDIS_NODES}
# 或者针对redis7使用下面方式创建
# 注意:最新版本`redis`通过`<pod-name>.<headless-service>`方式创建集群
kubectl exec -it redis-cluster-0 -- redis-cli --cluster create --cluster-replicas 1 redis-cluster-0.redis-cluster-headless:6379 redis-cluster-1.redis-cluster-headless:6379 redis-cluster-2.redis-cluster-headless:6379 redis-cluster-3.redis-cluster-headless:6379 redis-cluster-4.redis-cluster-headless:6379 redis-cluster-5.redis-cluster-headless:6379
# 或者
kubectl exec -it redis-cluster-0 -- redis-cli --cluster create redis-cluster-0.redis-cluster-headless:6379 redis-cluster-1.redis-cluster-headless:6379 redis-cluster-2.redis-cluster-headless:6379 redis-cluster-3.redis-cluster-headless:6379 redis-cluster-4.redis-cluster-headless:6379 redis-cluster-5.redis-cluster-headless:6379删除redis集群
./destroy-k8s.sh测试redis集群是否正常
查看集群状态是否正常
kubectl exec -it redis-cluster-0 -- redis-cli -c cluster info
kubectl exec -it redis-cluster-0 -- redis-cli -c cluster nodes通过set/get指令测试集群读写是否正常
# 测试写
kubectl exec -it redis-cluster-0 -- bash -c "for i in {1..15}; do redis-cli -c set key\$i value\$i 1>/dev/null && echo \"成功set key\$i value\$i\"; done"
# 测试读,能够读取所有key*值说明读正常
kubectl exec -it redis-cluster-0 -- bash -c "for i in {1..15}; do echo \"key\$i=\$(redis-cli -c get key\$i)\"; done"删除若干redis集群节点,再次查看数据是否会丢失
# 删除若干节点
kubectl delete pod redis-cluster-0
kubectl delete pod redis-cluster-1
kubectl delete pod redis-cluster-2
kubectl exec -it redis-cluster-0 -- redis-cli -c cluster info
# 测试读,能够读取所有key*值说明没有丢失数据
kubectl exec -it redis-cluster-0 -- bash -c "for i in {1..15}; do echo \"key\$i=\$(redis-cli -c get key\$i)\"; done"cluster模式管理
redis 集群原理详解
https://blog.csdn.net/a745233700/article/details/112691126redis 插槽
https://baijiahao.baidu.com/s?id=1767053233302021116&wfr=spider&for=pc
默认情况下,redis集群的读和写都是到master上去执行的,不支持slave节点读和写,跟Redis主从复制下读写分离不一样,因为redis集群的核心的理念,主要是使用slave做数据的热备,以及master故障时的主备切换,实现高可用的。Redis的读写分离,是为了横向任意扩展slave节点去支撑更大的读吞吐量。而redis集群架构下,本身master就是可以任意扩展的,如果想要支撑更大的读或写的吞吐量,都可以直接对master进行横向扩展。
使用以下示例辅助学习:
https://gitee.com/dexterleslie/demonstration/tree/master/demo-redis/redis-server/docker-based/mode-clusterhttps://gitee.com/dexterleslie/demonstration/tree/master/demo-redis/redis-jedis/jedis-cluster-loadhttps://gitee.com/dexterleslie/demonstration/tree/master/demo-redis/redistemplate/redistemplate-cluster
使用redis-cli创建redis集群
# redis7之前创建集群只支持ip地址,例如下面的xxx代表节点所在的ip地址
# 创建集群后依次为`6380`和`6383`互为主从、`6381`和`6384`互为主从、`6382`和`6385`互为主从
redis-cli --cluster create --cluster-replicas 1 xxx:6380 xxx:6381 xxx:6382 xxx:6383 xxx:6384 xxx:6385
# redis7之后创建集群支持使用节点DNS名称,例如下面的node1、node2
redis-cli --cluster create --cluster-replicas 1 node1:6379 node2:6379 node3:6379 node4:6379 node5:6379 node6:6379查看集群中所有节点信息
cluster nodes查看集群状态信息
cluster infofailover 测试
测试场景: 停止1、3、5节点集群依旧能够正常提供服务。
todo 同时停止1、3、5节点会导致集群无法恢复,必须要停止一个节点 failover 后再停止另外一个。
参考 链接 启动基于 redis6 的集群
模拟节点宕机自动 failover
登录节点 2 查看集群状态变化
bash# 登录节点 2 docker compose exec -it node2 bash # 显示集群状态为 ok redis-cli -h 127.0.0.1 -p 6381 cluster info # 显示集群节点状态 redis-cli -h 127.0.0.1 -p 6381 cluster nodes依次停止节点等待 failover 成功后再停止下一个节点
bash# 停止节点 node1 redis-cli -h 127.0.0.1 -p 6380 shutdown # 停止节点 node3 redis-cli -h 127.0.0.1 -p 6382 shutdown # 停止节点 node5 redis-cli -h 127.0.0.1 -p 6384 shutdown # 此时集群依旧能够正常提供服务 # 重新启动节点 node1、node3、node5,node1 和 node3 由原来的 master 节点自动切换为 slave 节点。 docker compose up -d
slave 节点手动 failover 实主从切换
可以通过次方式无感知迁移指定 master 节点到其他主机中。
登录 slave 节点 5
bash# 登录节点 5 docker compose exec -it node5 bash # 显示集群节点状态 redis-cli -h 127.0.0.1 -p 6380 cluster nodes手动 failover slave 节点 5
bashredis-cli -h 127.0.0.1 -p 6384 cluster failover查看集群状态
bash# 显示集群节点状态 redis-cli -h 127.0.0.1 -p 6380 cluster nodes # 此时可以看到 node5 被提升为 master 节点,node2 被降级为 node5 的 slave 节点最后可以安全地删除 node2 节点
在线扩容
新增节点
https://zhuanlan.zhihu.com/p/540573229?utm_id=0todo 使用redistemplate/redistemplate-cluster创造数据后添加节点会报告错误 CROSSSLOT Keys in request don't hash to the same slot
参考 链接 启动基于 redis6 的集群
添加新的 master 节点到集群中
启动新的 master 节点
bashdocker compose -f docker-compose-add-node.yml up -d登录新的 redis 节点,把新节点添加到 redis cluster 中
bash# 进入新节点的 shell 中 docker compose -f docker-compose-add-node.yml exec -it node-extra-master bash # 127.0.0.1:6390 为新的 master 节点 # 127.0.0.1:6380 为集群中已存在的任意一个节点 # 注意:此时新节点无法接收和处理请求,因为新节点还没有分配插槽 redis-cli --cluster add-node 127.0.0.1:6390 127.0.0.1:6380为新节点分配插槽
bash# 127.0.0.1:6380 为集群中现有的 master 节点 # 输入需要移动的插槽数 1000,然后输入接收插槽数据的新节点 id,输入 all 表示从所有现有的节点中抽取共 1000 个插槽并移动到新节点中,输入指定节点 id 表示从指定的节点抽取共 1000 个插槽并移动到新节点中 redis-cli --cluster reshard 127.0.0.1:6380查看集群状态,此时新的节点能够提供服务了
bashredis-cli -p 6380 cluster nodes
为 master 节点添加 slave 节点
启动新的 slave 节点
bashdocker compose -f docker-compose-add-node.yml up -d登录 slave 节点并添加新的 slave 节点到集群中
bash# 进入新节点的 shell 中 docker compose -f docker-compose-add-node.yml exec -it node-extra-slave bash # 添加节点到集群中 # 127.0.0.1:6391 为新的 slave 节点 # 127.0.0.1:6380 为集群中现有的节点 redis-cli --cluster add-node 127.0.0.1:6391 127.0.0.1:6380为指定的 master 节点添加 slave 节点
bash# 2728a594a0498e98e4b83a537e19f9a0a3790f38 为指定 master 节点的 id redis-cli -h 127.0.0.1 -p 6391 cluster replicate 2728a594a0498e98e4b83a537e19f9a0a3790f38查看集群状态
bashredis-cli -h 127.0.0.1 -p 6380 cluster nodes
在线缩容
新增节点
https://zhuanlan.zhihu.com/p/540573229?utm_id=0
参考 链接 启动基于 redis6 的集群
删除 slave 节点
登录被删除的 slave 节点
bashdocker compose -f docker-compose-add-node.yml exec -it node-extra-slave bash删除 slave 节点
bash# 获取 slave 节点信息 redis-cli -h 127.0.0.1 -p 6380 cluster nodes # 127.0.0.1:6391 是通过 cluster nodes 获取的 slave 节点 ip:port # 6b92155a7e8851b9842c4a3ec38ff9d2b230b33e 是通过 cluster nodes 获取的从 slave 节点 id redis-cli --cluster del-node 127.0.0.1:6391 6b92155a7e8851b9842c4a3ec38ff9d2b230b33e查看集群状态
bashredis-cli -h 127.0.0.1 -p 6380 cluster nodes
删除 master 节点
登录被删除的 master 节点
bashdocker compose -f docker-compose-add-node.yml exec -it node-extra-master bash迁移将要删除的 master 节点插槽到其他节点中
bash# todo 使用 reshard 删除节点不可取,研究使用其他方案 # 迁移将要删除的 master 节点插槽到其他节点中,根据提示将节点中所有插槽迁移,注意:sources ID 输入被删除的 master 节点 id,不能输入 all # 127.0.0.1:6390 将要被删除的 master 节点 redis-cli --cluster reshard 127.0.0.1:6390插槽迁移成功后,删除 master 节点
bash# todo 使用 forget 命令删除 master 节点 redis-cli --cluster del-node demo-redis-cluster-node-extra:6390 65999fa8f6dc13726008c35dfd0e60cec7e2c7da