redis学习

发布时间:2024年01月21日

redis集群 raft算法

Redis 集群是一种分布式 Redis 系统,可以在多个 Redis 实例之间共享数据
为了实现这一目的,Redis 集群使用了一种名为 Raft 的分布式一致性算法

Raft 算法是一种分布式一致性算法,专门用于解决分布式系统中的数据一致性问题
它通过维护一个复制的日志来保证数据的一致性。所有的 Redis 节点都会将写入请求记录到日志中
并通过网络协议来协商日志的提交顺序。用于管理集群状态的主 Redis 节点会将日志存储到磁盘,以便确保数据不会丢失。

总的来说,Redis 集群使用 Raft 算法来解决分布式系统中的数据一致性问题,并保证数据的安全性和可用性。

Raft优缺点

Raft算法是一种用于实现分布式系统中的一致性的算法。

优点:
易理解性: 相比Paxos算法,Raft更容易理解和实现。
强领导者: Raft使用明确的领导者来管理日志复制,简化了管理过程。
日志一致性: 保证所有复制日志的一致性,减少数据不一致的可能性。

缺点:
领导者单点故障: 虽然领导者选举机制可以在领导者失败时选出新领导者,但在此期间系统的可用性会受到影响。
日志复制延迟: 在某些情况下,日志复制的延迟可能会影响系统性能。

总的来说,Raft算法通过其易于理解和实现的特性,在分布式系统中实现了有效的一致性管理,尽管它也有其局限性。

Redis集群为什么是16384个哈希槽

Redis集群使用16384个哈希槽 (hash slot) 来决定一个特定的键应该被放到哪个节点上。
这是一种分布式的一致性哈希方案。

原理

当向Redis集群存储一个键值对时,Redis首先会计算键的CRC16值,然后取模16384
得到的结果就是这个键应该在哪个哈希槽中。
然后,Redis会在集群中查找这个哈希槽被分配给哪个节点,然后将键值对存储在相应节点上。

原因

使用16384个哈希槽的原因是它提供了一个适中的粒度大小,用于分布键和迁移节点。
如果哈希槽太少,会导致哈希槽不能平衡分布到各个节点
如果哈希槽太多,会影响查找效率,增加节点迁移和数据重分布的复杂性

使用16384个哈希槽,既可以保证各个节点之间的负载均衡,又可以在效率和复杂性之间取得一个平衡。
每个Redis节点都会知道所有的16384个哈希槽到底由哪个节点处理
这样可以使得客户端在访问一个键时能根据哈希槽定位到正确的节点,提高了读写性能
同时,这也使得当节点增加或减少时,可以通过重新分配哈希槽来实现节点之间的平衡。

举例

如果哈希槽太少,就意味着分片的粒度太大,数据分布可能会导致不均。
假设哈希槽只有10个,而Redis的集群节点有100个。
这种情况下,因为哈希槽的数量过少,导致无法将哈希槽平均地分配到每个节点上
所以就可能存在一种情况,就是某几个节点上承载了大量的哈希槽
而其他节点却没有,这就导致了数据在各个节点上的分布极其不均衡。

假设哈希槽是13484个,那么每个节点大约分配到134个哈希槽(实际情况会根据键的分布情况有所不同)
这样一来,每个节点承载的数据就会更加均衡,不会出现某个节点数据过多,负载过高的情况。

在设计Redis集群的哈希槽数量时,需要考虑的因素就是要确保数据能够在所有节点上均匀地分布
以达到最好的负载均衡效果
少量的哈希槽使得数据无法在节点间均匀分布,大量的哈希槽可能增加数据管理的复杂性和难度
16384个哈希槽是一个在实践中被证明效果较好的选择。

个人理解

16384等于2的14次方
计算机中的哈希通常都是基于2的一些次方来进行设计,这样可以更好地利用内存,提高计算效率

  • 二进制系统
    在计算机内部,所有的信息都以二进制(0或1)的形式存储与处理
    2的幂在底层硬件和计算过程中更加自然和有效
  • 计算效率
    使用2的幂可以简化计算
    使用2的幂可以通过移位操作来代替除法操作,大大提高了运算效率
  • 优化存储
    在数据存储方面,使用2的幂可以带来许多优化
    例如在内存分配中,由于内存页通常是2的幂(例如4096字节)
    所以分配2的幂大小的内存框更容易并且减少了内存碎片
  • 哈希算法
    在哈希算法中,使用2的幂作为桶的数量,可以使得哈希值更均匀地分布在各个桶中
    提高哈希的效率和性能

Redis支持的运行模式

  • 单实例模式
    最简单的Redis运行模式,按照默认配置启动Redis服务即可进入该模式

  • 主从复制模式
    Redis可以配置成Master-Slave模式,即一个Master节点和一个或多个Slave节点。
    所有的写操作都发生在Master节点,然后Master将写操作都同步到Slave节点,读操作由Slave节点来处理。

  • 哨兵模式(自动处理主节点宕机和故障转移)
    在主从复制的基础上添加了Sentinel节点,当主节点宕机后,Sentinel可以自动将从节点提升为主节点,从而实现高可用。

  • 集群模式(自动处理主节点宕机和故障转移)
    Redis Cluster节点之间通过gossip协议通信,数据按照一定的哈希算法分布在各个节点中
    它包含多个Master节点和每个Master的Slave节点。集群模式自带数据分片和高可用能力。

对一致性要求不高,读多写少的场景可以选择主从复制模式,保证读取的高效
对高可用性有要求时可以选择哨兵模式
需要处理大量数据时可以选择集群模式(可扩展,通过加机器来实现;高可用;)

分布式方案~最开始的主从复制

主节点Master,从节点Slave。Slave会通过复制的技术,自动同步Master的数据

同步步骤

  • Slave启动,连接到Master
  • Slave向Master发送SYNC命令
  • Master接收到SYNC命令后,开始在后台保存其数据快照(RDB文件)
    同时,Master记录从现在开始执行的所有写命令,这就是所谓的缓冲区。
  • 当快照完成时,Master将快照文件发送给Slave,Slave将文件保存到磁盘,然后载入到内存。
  • Master将所有写命令的缓冲区中的内容发送给Slave,Slave执行这些命令,从而实现和Master一致的状态。
  • 以后Master每执行一个写命令,都会将写命令异步地发送给Slave,Slave接收并执行接收到的写命令
    保持和Master的同步。

Slave总是试图保持跟Master数据库的同步。
注意
如果有多个Slave,Master会对每个Slave分别进行复制,且每个Slave的复制过程彼此没有任何关系
这就意味着Master可以同时和多个Slave处于不同的复制阶段

Redis 的 Partial resynchronization

从Redis 2.8版本开始,引入了一种叫做Partial resynchronization 部分重新同步的策略
即在网络中断后,Slave在重新连接Master时,并不总是全量复制
而是尝试进行增量复制。这大大优化了网络资源的利用,避免频繁全量复制带来的影响

节点切换步骤

  • 登陆到Slave节点的机器
  • 修改Redis配置文件。将slaveof指令注释掉或者删除
    将其注释掉或者删除:

    slaveof master_host master_port

  • 保存配置并重启Redis服务。这会使Redis服务以Master模式启动。
  • 如果Redis服务正在运行,需要先停止它,然后再启动。
    sudo service redis-server stop
    sudo service redis-server start
  • 更新其他Slave节点的配置。登陆到每个Slave节点的机器,修改它们的配置
    将slaveof指令的master_host和master_port改为新的Master节点的host和port,然后重启Redis服务

问题

Redis主从复制解决了数据备份和部分性能的问题,但是没有解决高可用的问题
在一主一从或者一主多从的情况下,如果主服务器挂了,对外提供的服务就不可用了
需要手动把从服务器切换成主服务器,然后再把剩余节点设置为它的从节点
这个比较费时,还会造成一定时间的服务不可用。

分布式方案~哨兵模式与选举过程

Redis哨兵(Sentinel)模式用于管理多个Redis服务器,提供高可用性
它可以监控Redis主从服务器,进行自动故障转移

(典型的哨兵集群监控)
在这里插入图片描述

  • 故障检测
    当主节点出现故障时,哨兵之间通过交换消息来确认主节点确实不可用
  • 发起选举
    一旦某个哨兵确定主节点不可用,故障检测超时后(在未收到对ping命令的响应后)
    它会向其他哨兵发送请求,要求将自己选为领导者
  • 哨兵投票
    其他哨兵收到请求后,根据各自的情况进行投票
  • 选举产生领导哨兵
    收到大多数哨兵选票的哨兵成为领导者
  • 执行故障转移
    领导哨兵负责执行故障转移操作,比如提升某个从节点为新的主节点

Sentinel既监控所有的Redis服务,Sentinel之间也相互监控。
Sentinel本身没有主从之分,地位是平等的,只有Redis服务节点有主从之分。
Sentinel通过Raft共识算法,实现Sentinel选举,选举出一个leader来,由leader完成故障转移。
Raft算法的核心思想是:先到先得,少数服从多数。

脑裂问题(Split-Brain)

在Redis哨兵模式下,由于通信问题导致的网络分区可能会引发脑裂问题

Redis的哨兵模式虽然提供了高可用性的方案,但是在某些情况下还是可能出现脑裂(split-brain)问题。
这主要发生在网络分区或者哨兵节点失效的情况下。

脑裂是一个通用的分布式系统问题,一般是指在网络分区或通信故障等情况下
系统的节点被切割成两个或更多的独立的部分,而每个部分都认为自己是唯一活跃的部分,这就可能导致数据不一致。

在Redis哨兵模式下,可能出现的脑裂问题大致有以下两种情况:

  • 网络分区
    例如,主节点与一部分哨兵节点失去联系,而这些哨兵与其他哨兵和从节点之间的网络仍然正常
    如果此时这些哨兵判断主节点宕机,并把从节点提升为新的主节点,同时原主节点和其他哨兵仍然正常运行
    这就导致了同时存在两个主节点,也就是脑裂
  • 多数派哨兵失效
    例如有5个哨兵,如果突然有3个哨兵宕机,此时只剩下2个哨兵,不足以完成故障切换

为了避免脑裂问题,通常会确保在任何时刻都有超过半数的哨兵在运行,以保证能统一看到并决定系统的状态
同时,哨兵应分布在不同的物理机器或网络中,以避免单点故障。

Redis的哨兵是每个节点都有一个吗

Redis的哨兵模式(Sentinel mode)是Redis的高可用方案。
它通过哨兵节点来监控Redis主从集群的运行状态,如果发现主节点宕机,哨兵会自动将从节点提升为新的主节点。
哨兵并非每个节点都有一个,而是可以根据实际需要独立部署一到多个哨兵节点。
通常情况下,哨兵应至少有三个实例,以便在丢失一个哨兵实例时仍能正常运行。

每个哨兵节点都会独立地监控所有的主从节点,当它们监测到主节点宕机后
会通过投票的方式选出一个哨兵来完成故障转移操作
达到投票阈值(一般是哨兵数的一半加一)的哨兵会将从属节点提升为新的主节点,并更新相应节点的配置。

哨兵节点没有必要和Redis数据节点部署在同一台服务器上,它们可以独立部署
通常在生产环境中,为了保证高可用性,哨兵节点会被部署在不同的物理服务器上
这样即使一台服务器宕机,仍然可以保证哨兵的正常运行。

缺点总结

主从切换的过程中会丢失数据,因为只有一个master;
只能单点写,没有解决水平扩容的问题

分布式方案~Cluster

Redis Cluster是在Redis 3.0的版本正式推出的,用来解决分布式的需求,同时也可以实现高可用
它是去中心化的,客户端可以连接到任意一个可用的节点。
Redis Cluster可以看成是由多个Redis实例组成的数据集合。
客户端不需要关注数据的子集到底存储在哪个节点,只需要关注这个集合整体。
在这里插入图片描述
Redis创建了16384个槽(slot),每个节点负责一定区间的slot
比如Node1负责0-5460,Node2负责5461-10922,Node3负责10923-16383。

对Key用CRC16算法计算再%16384,得到一个slot的值,数据落到负责这个slot的Redis节点
查看Key属于哪个slot:
cluster keyslot jack

key与slot的关系是永远不会变的,会变的只有slot和Redis节点的关系

可以将某个key自定义slot不?

可以
让很多个key同时落在同一个节点,只需要在key里面加入{hash tag}即可
Redis在计算槽编号的时候只会获取{}之间的字符串进行槽编号计算
user{666}base=…

主从切换过程

当slave发现自己的master变成FAIL状态时,便尝试进行Failover,以期成为新的master。
由于挂掉的master可能会有多个slave,从而存在多个slave竞争成为master节点的过程

  • slave发现自己的master变成FAIL(心跳检查失败)
  • 将自己记录的集群currentEpoch加1,并广播FAILOVER_AUTH_REQUEST信息
  • 其他节点收到该信息,只有其他master响应,判断请求者的合法性,并发送FAILOVER_AUTH_ACK
    对每一个epoch只发送一次ack
  • 尝试failover的slave收集FAILOVER_AUTH_ACK
  • 超过半数后变成新的Master
  • 广播Pong消息通知其他集群节点

切换示例

比如A、B、C三个节点(每个节点1主2从)组成集群,A的master挂了,A的两个从节点发起选举
结果B的master投给A的从节点A1,C的master投给了A的从节点A2
这样就会发起第二次选举,选举轮次+1继续上面的流程

事实上从节点并不是在主节点一进入 FAIL 状态就马上尝试发起选举,而是有一定延迟
一定的延迟确保等待FAIL状态在集群中传播
slave如果立即尝试选举,其它masters或许尚未意识到FAIL状态,可能会拒绝投票

水平扩容时的动作

无缝的增加和删除节点,同时不会像传统的一致性哈希那样造成大量的数据迁移
当有哈希槽正在进行迁移时,不能对Cluster进行故障恢复操作
同时哈希槽迁移也会对Redis Cluster的性能造成一定影响
所以哈希槽的迁移通常是在数据访问量较低的情况下进行

Redis Cluster特点

  • 去中心化
  • 数据按照Slot存储分布在多个节点,节点间数据共享,可动态调整数据分布
  • 可扩展性,可线性扩展到1000个节点(官网推荐不超过1000个),节点可动态添加/删除
  • 高可用性,部分节点不可用时,集群仍可用
    通过增加Slave做standby数据副本,能够实现故障自动failover
    节点之间通过gossip协议交换状态信息,用投票机制完成Slave到Master的角色提升
  • 降低运维成本,提高系统的扩展性和可用性

Redis中两种不同的数据持久化方式

RDB(Redis DataBase file)

Redis使用的Snapshot快照式存储方式
在某一时刻通过dump实现将数据写入一个临时文件
临时文件生成完毕后,再用这个临时文件替换上一次的快照文件,完成数据备份

RDB由Redis自动完成,可以设置不同的策略决定在什么情况下将内存数据写入磁盘文件。
通过配置,可以设置在数据改动达到一定数目,并且时间达到一定长度时保存RDB文件到磁盘
RDB对Redis的性能影响最小,因为主要的I/O操作都是在后台完成
但由于RDB使用的是快照存储,如果Redis意外宕机,最近的数据可能丢失

AOF(Append Only File)

Redis提供的另一种持久化方式

AOF采用日志的形式来记录每个写操作,将Redis执行过的所有写指令记录下来。
Redis启动之初会读取该文件重新构建数据,从而实现数据的恢复。
AOF文件的更新采用追加方式,对于每一条修改数据的命令,Redis都会写入AOF文件

AOF文件通常会比RDB文件大

同时也可以设置AOF的更新频率,如每秒更新或者每次有数据修改就更新等。
AOF相比RDB在持久化方面提供了更好的数据完整性保证,但可能会有一些性能上的开销。

在Redis中,可以同时开启RDB和AOF

当Redis重启的时候会优先载入AOF文件重建数据,因为AOF文件的数据通常是最完整的。
同时,也可以根据应用的需求选择只开启RDB或者AOF

水平扩容 和 垂直扩容

水平扩容,又称为横向扩展(Scale-out),是一种增加系统处理能力的策略
是通过添加更多的机器到现有的资源池中来提升系统的性能和存储能力。

垂直扩容,又称为纵向扩展(Scale-up),主要是通过提升单个节点的硬件性能
比如增加更好的CPU、更大的内存、更大的硬盘等。

水平扩容的优势包括:
负载均衡:通过多节点分摊任务,可以更好地处理并发请求,提高计算和IO性能。
高可用:即使其中一个或多个节点宕机,仍有其他节点提供服务。
灵活性:可以根据业务需求灵活增减节点,无需暂停服务。
成本效益:采用多台中低端服务器扩展对比单台高端服务器来说,经济成本低,性价比高。

Failover

Failover是一种备份操作方式,用于系统或组件的故障时自动切换到备用系统或组件
这种切换可以是预先计划好的,如服务器的维护过程中,也可以是由系统故障引起的。

在许多系统中,Failover过程可以被自动化。
当主系统下线时,备用系统能够自动接管工作,提供连续不断的服务,以减少系统停机时间,保持服务的可用性。
例如,在数据库领域,一个备用数据库可以复制一个主数据库的所有操作。
当主数据库崩溃时,系统可以自动切换到备用数据库。

同样,在Redis的主从复制模式中,
如果主节点出现故障,Redis的哨兵模式(Sentinel)就能自动将从节点提升为主节点
以实现高可用的Failover过程

Failover是在分布式系统中保证高可用和故障恢复的重要机制。

参考文档

https://juejin.cn/post/6987758024064499726

文章来源:https://blog.csdn.net/wangkai6666/article/details/135723085
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。