Redis能保证数据不丢失吗?-高级策略

时间:2024-02-23 16:32:34

从对基础策略的分析中我们了解到即使采用AOF日志,因为写日志的延迟,数据仍存在丢失的可能性。而且即使数据都写入到了硬盘,也无法处理单机硬盘故障导致数据丢失的问题。

这一小节就让我们来看下处理这个问题的一些高级策略,包括主从架构、哨兵系统和集群架构。这些策略可以提高数据的安全性和可用性。

主从架构实现多副本保存

在Redis的主从架构中,数据会从一个主节点复制到一个或多个从节点。这样做的好处是,即使主节点出现问题,我们也可以从从节点中恢复数据,而且从节点可以继续提供查询服务。

工作原理:主节点负责处理所有的写操作,并将这些操作记录同步到从节点。从节点则可以处理读请求,分担主节点的读负载。

优点

  • 数据冗余:通过在多个从节点上保存数据副本,提高了数据的可靠性。
  • 读负载均衡:从节点可以处理读请求,帮助分担主节点的读负载。

配置示例:

# 从节点配置 
slaveof <masterip> <masterport>

主节点无需特别配置,只需正常启动。从节点的配置文件中增加slaveof配置,masterip、masterport是主节点的IP和端口。

哨兵系统实现故障转移

哨兵系统(Sentinel)是一种用于监控Redis主从节点状态的系统,能够在主节点故障时自动进行故障转移。

工作原理:哨兵通过发送命令,检查主从节点的健康状态。如果主节点不可达,哨兵会自动将其中一个从节点提升为新的主节点,并更新其他从节点以指向新的主节点。

优点:

  • 自动故障转移:提高了系统的可用性,当主节点出现故障时,能够快速恢复。
  • 监控:哨兵还负责监控Redis节点的运行状态,提供了一定程度的自动管理。

配置示例:

# 哨兵配置文件 sentinel.conf
sentinel monitor mymaster <masterip> <masterport> 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1
  • sentinel monitor mymaster:这条命令让哨兵监控一个名为 mymaster 的主节点,其IP和端口分别为 masterip 和 masterport 。数字2表示当至少有两个哨兵认为主节点不可达时,才会进行故障转移。这是为了避免因为网络闪断导致的误判。这也告诉我们如果需要更高的可用性,哨兵进程也要部署多个,一般3个或5个就够了。
  • sentinel down-after-milliseconds mymaster 5000:设置哨兵判断主节点为“下线”的时间。例如,这里设置为5000毫秒(5秒),如果哨兵在这段时间内无法达到主节点,则认为主节点下线。因为各种原因,哨兵可能会出现误判的问题,多等一会说不定又能访问主节点。
  • sentinel failover-timeout mymaster 60000:设置故障转移的超时时间,单位是毫秒。在这个例子中,设置为60000毫秒(60秒)。如果故障转移操作在这段时间内没有完成,则会被取消。
  • sentinel parallel-syncs mymaster 1:设置在故障转移后,同时可以有多少个从节点同时对新的主节点进行同步。这里设置为1,意味着一次只有一个从节点可以同步。在故障转移后,所有从服务器都需要与新的主服务器进行全量同步以保证数据一致性。由于全量同步会阻塞从节点,并且可能会消耗较大的网络带宽和CPU资源,所以通过限制并发同步的从节点数量,可以避免过多从节点同时进行同步带来的资源压力过大问题。

集群架构实现数据冗余

Redis集群通过分片的方式来存储数据,每个分片存储不同的数据。通过多个节点的协作,实现数据的冗余和分布式存储。

工作原理:Redis集群将所有的数据分为16384个哈希槽,每个节点负责一部分哈希槽。客户端根据特定的哈希规则,将数据存储到相应的节点上。

优点

  • 数据分片:实现了数据的自动分片,便于管理大规模数据。
  • 高可用性:集群中的节点可以相互备份,即使部分节点失败,也不会影响整个集群的可用性。

配置示例: 配置Redis集群涉及到启动多个Redis实例,可使用redis-cli工具创建集群:

# 启动Redis实例(假设启动6个实例作为示例)
redis-server --port 7000 --cluster-enabled yes --cluster-config-file nodes-7000.conf --cluster-node-timeout 5000 --appendonly yes --appendfilename appendonly-7000.aof --dbfilename dump-7000.rdb --logfile 7000.log
# 重复上述命令,修改端口为7001-7005

# 使用redis-cli创建集群
redis-cli --cluster create <ip1>:7000 <ip2>:7001 <ip3>:7002 <ip4>:7003 <ip5>:7004 <ip6>:7005 --cluster-replicas 1
  • --cluster-enabled yes:启用Redis集群模式。
  • --cluster-config-file nodes-7000.conf:指定集群的配置文件。这个文件由Redis自动维护,记录了集群中所有节点的信息。
  • --cluster-node-timeout 5000:设置节点超时时间,单位是毫秒。如果一个节点在这段时间内没有响应,集群会认为该节点已经下线。
  • --appendonly yes:启用AOF持久化模式。在集群模式下,推荐使用AOF持久化来保证数据安全。
  • --appendfilename appendonly-7000.aof:指定AOF文件的名字。这里根据不同的端口号,为每个实例指定了不同的AOF文件名,以避免冲突。
  • --dbfilename dump-7000.rdb:指定RDB文件的名字。同样地,根据不同的端口号为每个实例指定了不同的RDB文件名。
  • --logfile 7000.log:指定日志文件的名字。这有助于在出现问题时进行故障排查。

通过主从架构、哨兵系统和集群架构,可以有效地实现数据的多副本保存、故障转移和数据冗余,提高系统的可靠性和可用性,基本上可以避免单机系统的数据丢失问题。

跨机房部署

服务器所在的机房也可能出现问题,比如光缆被挖断了、空调系统坏了、机房着火了等实际出现过的状况,为了解决这些问题,我们还可以通过跨机房的方法来提升Redis的数据可靠性和可用性。

  • 在不同机房间部署主从复制架构。在一个数据中心内设置主节点,在另一个或多个数据中心设置从节点。
  • Sentinel(哨兵)集群也应跨机房部署,以避免单点故障。
  • 使用Redis Cluster进行跨机房部署,每个机房都可以有多个分片(shard),并且每个分片的主节点和从节点分别位于不同的地理位置,这样即使一个机房完全不可用,其他机房的副本仍然能够提供服务。

跨机房部署时需要自行解决网络的通信问题,让各个节点之间可以无障碍的相互访问,机房间最好使用低延迟、高带宽的专线连接,以加速数据同步过程并降低网络问题导致的数据不一致风险。

还有面试中经常提及的两地三中心的多活架构,也可以安排上。每个机房都部署一套完整的、独立处理读写请求的Redis集群,并通过分布式锁或者数据同步中间件等技术保证各个集群间数据的一致性。

  • 分布式锁可以采用ZooKeeper、etcd、redis等,确保在多个数据中心进行同步更新时,只有一个数据中心的Redis集群在给定时间内对某个资源拥有写权限。
  • 数据同步中间件主要用于实时或近实时地将一个数据中心的写入操作同步到另一个数据中心。可以使用消息队列、专业的数据同步工具(比如阿里巴巴开源的Canal)等。
  • 多活架构还要设计数据分片策略、数据路由机制以及事务处理方式,比如根据地域或者一致性Hash分片来区分用户,然后使用客户端驱动路由或者网关路由来把用户导向不同的机房,最后使用分布式事务提交数据。

多活架构比较复杂,我也没有实际搞过,这里就不多说了。