一、单机模式
单机模式就是在一台服务器上安装redis,然后启动,所有业务都调用这一台redis服务器。
优点:
- 部署简单,只需要在一台服务器上安装并启动redis就行。
- 成本低,没有备用节点,不需要其他的开支。
- 高性能,单机不需要同步数据,数据天然一致性。
缺点:
- 可靠性较弱,一旦服务器宕机,所有业务都无法使用redis服务。
- 单机模式redis性能受限于CPU的处理能力。
二、主从模式
主从模式是指有多台redis服务器,其中一台主要负责写入客户端请求数据,称为主节点(master),其他服务专门负责处理客户端的读取数据的请求,不负责写入数据,称为从节点(slave)。主节点写入的数据会复制的各个从节点上,并且数据复制的方向是单向的,只能从主节点复制到从节点。
主从模式搭建:
- 在多台服务器上搭建redis服务。
- 修改所有作为slave节点的服务器上Redis的配置文件,指定要同步的 Master 节点 IP 和端口。
replicaof 192.168.126.1 6379
- 启动所有节点就可以了。
具体工作机制:
- slave启动后,向master发送SYNC命令,master接收到SYNC命令后通过bgsave将当前主节点的全量数据以rdb的方式保存快照,同时使用缓冲区记录后续主节点执行的增量数据。
- master将保存的快照文件发送给slave。
- slave接收到快照文件后,加载快照文件,载入数据。
- 当slave节点复制完全量数据后,主节点在将后续的增量数据同步给slave节点,slave接收命令并执行,完成复制初始化。
- 此后master每次执行一个写命令都会同步发送给slave,保持master与slave之间数据的一致性。
优点:
- 读写分离:master写,slave读,同时可以根据访问需求大小来添加slave节点数量。
- 负载均衡:通过读写分离的方式来分但服务器负载,主节点负责写入数据,多个从节点负责读取数据,缓解单个服务器访问的压力,提高读的吞吐量。
- 数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
- 高可用性:提高了服务的可用性,多个节点同时提供服务,当前其中一台节点宕机后,其他节点仍然可以提供服务。
- 故障恢复:master宕机后,快速升级slave为master。
缺点:
- master宕机后,slave节点升级成新的master节点后,需要手动切换主机,同时会有部分数据不能及时同步从服务器,造成数据不一致。
- slave宕机后,多个slave恢复后,大量的SYNC同步会造成master IO压力倍增。
- 主从模式只有一个maste节点,所以master节点的写数据的能力会受到单机的限制。
三、哨兵模式
哨兵模式主要是在主从复制模式基础上,增加了自动化的故障恢复功能。因为主从复制模式下,当master节点宕机后,虽然slave节点会升级成新的master节点,但是升级后的slave节点的ip顺其自然的就称为了新的master节点ip,原先其他的slave节点配置的master节点的ip也是需要变更的,在主从复制模式下,这种变更是需要人工手动去修改配置文件的。而哨兵模式则完美的解决了这一缺陷,实现了快速的自动恢复,不再需要人工修改。
哨兵集群搭建:
需要注意到是每个哨兵都是一个独立的redis服务,只是不提供数据的读取服务。一般哨兵模式都是以集群的方式部署,每个哨兵都部署在不同的服务器上,且每个哨兵的配置文件除了ip和端口不一样,其他基本都是一样。一般集群中包含的哨兵数目都为奇数。
-
在服务器上搭建redis服务。
-
在redis目录下,创建哨兵的配置文件,文件名只能是sentinel.conf。
-
编辑sentinel.conf配置文件,设置哨兵的相关属性。
–后台运行
daemonize yes
–本机IP
bind 192.168.11.1
–sentinel端口号
port 26372
–指定pid文件
pidfile “/var/run/redis-sentinel.pid”
–指定log文件
logfile “/home/redis/redis/sentinel.log”
–指定工作目录
dir “/home/redis/redis”
–避免脚本重置,默认值yes
sentinel deny-scripts-reconfig yes
–监听节点,monitor 后面依次我需要监听的节点名、节点ip、节点端口、最后的2表示如果有两台服务器认定master已死,则宣传master死记。
sentinel monitor mymaster 192.168.11.152 7001 2
– 30秒连接不上mymaster 节点,则判断定mymaster 已死
sentinel down-after-milliseconds mymaster 30000
– 主备切换时,最多有多少个slave同时对新的master进行同步,这里设置为默认的1
sentinel parallel-syncs mymaster 1
– 3分钟同步没完成算超时
sentinel failover-timeout mymaster 180000 -
先启动master再启动slave,再启动哨兵。
哨兵的主要功能:
- 集群监控:负责监控 master 和 slave 进程是否正常工作。
- 消息通知:如果某个 Redis 实例宕机,那么哨兵负责向(哨兵间,客户端)发送消息。
- 自动故障转移:当master宕机后,由哨兵负责重新在slave节点中选举出新的master节点,并将其他slave连接到新的master,以及告知客户端新的服务器地址。更好的为客户端提供高可用服务。
哨兵模式的缺点:
哨兵的部署会占用额外的服务器资源,且不提供数据的读取服务。哨兵模式除了解决了主从模式手动切换主从节点的问题外,其他主从模式存在的问题,哨兵模式基本也都存在。
四、集群模式
-
redis集群解决了哪些问题?
主从模式实现了数据的热备份,哨兵模式实现了redis的高可用。但是这两种模式存在两个问题:
(1)写并发:这两种都只能有一个master节点负责写操作,在高并发的写操作场景,master节点就会成为性能瓶颈。而redis集群则可以实现多个节点同时提供写操作,redis集群模式采用无中心结构,每个节点都可以看做是一个主从模式,节点之间互相连接从而知道整个集群状态。
(2)海量数据的存储压力:无论是哨兵模式还是主从模式,每台机器上存储的数据都是一样的,都是从主节点上复制过去的,本质上只有一台Master作为存储。所以无论增加多少slave节点都无法解决单台机器存储的上限问题。但是集群模式就解决了这以问题,因为Redis Cluster是一种服务器 Sharding 技术,采用数据分片的方式,将不同的数据存储在不同的master节点上面,因为我们可以通过不断的增加集群中的节点,从而达到存储海量数据。 -
redis集群的实现原理?
Redis集群采用去中心化的思想,没有中心节点的说法,对于客户端来说,整个集群可以看成一个整体,可以连接任意一个节点进行操作,就像操作单一Redis实例一样,不需要任何代理中间件,当客户端操作的key没有分配到该node上时,Redis会返回转向指令,指向正确的node。 Redis也内置了高可用机制,支持N个master节点,每个master节点都可以挂载多个slave节点,当master节点挂掉时,集群会提升它的某个slave节点作为新的master节点。Redis集群可以看成多个主从架构组合起来的,每一个主从架构可以看成一个节点(其中,只有master节点具有处理请求的能力,slave节点主要是用于节点的高可用)。
-
分布式寻址算法
(1)hash算法:将key使用hash算法计算之后,按照节点数量来取余,即hash(key)%N。如果增加一个redis,映射公式变成了 hash(key)%(N+1)。如果一个redis宕机了,映射公式变成了 hash(key)%(N-1)。
优点就是比较简单,但是扩容或者摘除节点时需要重新根据映射关系计算,会导致数据重新迁移,从而造成数据库访问的压力陡增。
(2)一致性hash算法:将所有的存储节点排列在首尾相接的hash环上,各个节点通常是以节点的ip或者主机名进行hash计算来得到排列在hash环上的具体位置。然后每个key在计算Hash后会得到排列在hash环上的具体位置,最后分布在hash环上的key会顺时针找到最近的存储节点存放。优点是在加入和删除节点时只影响该节点与之逆时针方向最近一个节点之间的数据,缺点是数据的分布和节点的位置有关,因为这些节点不是均匀的分布在哈希环上的,所以数据在进行存储时达不到均匀分布的效果,可能造成雪崩效应。
(3)hash slot 算法:hash槽算法主要为了解决一致性hash算法数据倾斜不一致性的问题,所谓的槽其实就是一个数组。Redis集群有16384 个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽,集群的每个节点负责一部分hash槽。客户端可能会挑选任意一个redis实例去发送命令,接收到命令的redis实例都会计算key对应的hash slot,如果在本地就在本地处理,否则返回moved给客户端,让客户端进行重定向到hash slot对应的节点上去处理。优点是解耦数据和节点之间的关系,简化了节点扩容和收缩难度。节点自身维护槽的映射关系,支持节点、槽、键之间的映射查询,用于数据路由、在线伸缩等场景。 -
节点间的内部通信机制
redis cluster节点间采取gossip协议进行通信,跟集中式不同,不是将集群元数据(节点信息,故障,等等)集中存储在某个节点上,而是互相之间不断通信,保持整个集群所有节点的数据是完整的。- 集中式:的好处在于节点信息的更新和读取时效性非常好,所有节点的元数据信息都集中式的存储在一起,一旦某个节点元数据出现了变更,立即就更新到集中式的存储中。不好在于,所有的元数据的跟新压力全部集中在一个地方,可能会导致元数据的存储有压力。
- gossip:好处在于,将元数据的更新分散到各个节点上,不再集中在一个地方处理,降低了集中式处理的压力,但是有一定的延时,可能导致集群的一些操作会有一些滞后。且gossip 协议对服务器时间的要求较高,时间戳不准确会影响节点判断消息的有效性。随着节点数量增多后的节点间频繁的通信会导致网络开销增加,同时结点数太多,意味着达到最终一致性的时间也相对变长,因此官方推荐最大节点数为1000左右。
- 通信端口
每个节点都有一个专门用于节点间通信的端口,就是自己提供服务的端口号+10000,比如8011,那么用于节点间通信的就是18011端口。 - 交换的信息
节点间的通信主要有:故障信息,节点的增加和移除,hash slot信息,等等。 - gossip常见协议类型
gossip协议常见的消息类型包含: ping、pong、meet、fail等等。
(1)meet: 某个节点发送meet给新加入的节点,让新节点加入集群中,然后新节点就会开始与其他节点进行通信。
(2)ping:用于交换节点的元数据。每个节点每秒会向集群中其他节点发送 ping 消息,消息中封装了自身节点状态还有其他部分节点的状态数据,也包括自身所管理的槽信息等等。
(3)pong:ping和meet消息的响应,同样包含了自身节点的状态和集群元数据信息。
(4)fail:某个节点判断另一个节点 fail 之后,向集群所有节点广播该节点挂掉的消息,其他节点收到消息后标记已下线。
-
集群的扩容与收缩
集群主要是采用hash slot 算法进行寻址的,由于集群hash槽的数目是固定的,所以随着集群中节点数目的增减,每个节点所负责的hash槽的数目也会随之发生变化,因此对应槽和数据都会在节点之间移动。
1.扩容步骤:
(1)启动新节点;
(2)刚启动的新节点是没有和其他节点进行通讯的,因此需要在集群中任意节点执行 cluster meet 命令让新节点加入到集群中;
(3)新的节点加入到集群后,迁移槽和数据,将一些槽和数据从旧节点迁移到新节点;
(4)槽和数据迁移到新加入的节点后,新的节点会向集群中的各个主节点广播通知迁移过来的槽,并更新自身的槽节点对应表。 -
收缩步骤:
(1)迁移槽,首先判断要下线的节点是否有负责的槽,如果有,则先将该节点下的槽全部迁移到其他节点,否则直接删除该节点。
(2)通知集群的各个节点忘记自己。