一、主从架构搭建
为什么要进行主从架构搭建,一台redis不行吗?
①、持久化后的数据只在一台机器上,因此当硬件发生故障时,比如主板或CPU坏了,这时候无法重启服务器,有什么办法可以保证服务器发生故障时数据的安全性?或者可以快速恢复数据呢?
②、一台机器的内存容量瓶颈问题,搭建多台redis能够提高最大容量
主从架构介绍
redis提供了复制(replication)的功能,通过"主从(一主多从)"和"集群(多主多从)"的方式对redis的服务进行水平扩展,用多台redis服务器共同构建一个高可用的redis服务系统。
如何实现主从服务器之间的数据复制同步?
策略1 :一主多从 主机(写),从机(读)
策略2:薪火相传(可以由一部分从节点同步给其他从节点)
主从同步原理剖析
Redis
的主从复制是异步复制,异步分为两个方面
- 一个是
master
服务器在将数据同步到slave
时是异步的,因此master服务器在这里仍然可以接收其他请求 - 一个是slave在接收同步数据也是异步的。
全量同步
master
服务器会将自己的rdb
文件发送给slave
服务器进行数据同步,并记录同步期间的其他写入,再发送给slave
服务器,以达到完全同步的目的,这种方式称为全量复制。
主从服务器在完成第一次同步后,双方之间就会维护一个TCP连接(长连接),更方便的传输写操作命令
增量同步
因为各种原因 master 服务器与slave 服务器断开后,slave 服务器在重新连上master服务器时会尝试重新获取断开后未同步的数据即部分同步,或者称为部分复制。
在全量同步中有一个offset,这表明我当前同步到哪个数据了(和kafka有点类似),主服务器有一个环装的数据结构,也就是哪个缓冲区,当从服务器在第一步发过来的offset与主服务器在这个期间产生的新的offset(产生新的命令)差值到达了环装缓冲区的阈值(一圈后),那就要全量同步,否则就只同步这个差值即可,也就是增量同步
主从架构部署演示
有三种方式配置从节点
(1)配置文件:在从服务器的配置文件中加入:slaveof
(2)redis-server启动命令后加入 --slaveof
(3)Redis服务器启动后,直接通过客户端执行命令:slaveof ,则该Redis实例成为从节点
基于第二种方式演示
1、开启三个redis服务
redis-server ./redis.conf --port 6379
redis-server ./redis.conf --port 6380
redis-server ./redis.conf --port 6381
2、通过 info replication 命令查看三台节点角色
初始状态,三台节点都是master
3、设置主从关系,从节点执行命令:SLAVEOF 127.0.0.1 6379
4、接下来再查看,就已经变成slave的角色了
通过SLAVE OF 127.0.0.1 6379 ,如果主节点6379以前还存在一些key,那么执行命令之后,从节点会将以前的信息也都复制过来
5、主从读写分离
尝试在slave进行写操作
注:需要在redis.conf中配置replica-read-only yes
如果我们将其修改为 no 之后,执行写命令是可以的,但是从节点写命令的数据从节点或者主节点都不能获取的。
sentinel哨兵模式
通过前面的配置,主节点Master 只有一个,一旦主节点挂掉之后,从节点没法担起主节点的任务,那么整个系统也无法运行。
如果主节点挂掉之后,从节点能够自动变成主节点,那么问题就解决了,于是哨兵模式诞生了。
哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行。其原理是哨兵通过发送命令,等待Redis服务器响应(类似于心跳机制),从而监控运行的多个Redis实例。
哨兵搭建
二、redis-cluster搭建
1、基本概念分析
我们先来看一下,主从+哨兵模式,有什么问题?
(1)在主从 + 哨兵模式中,仍然只有一个Master节点。当并发写请求较大时,哨兵模式并不能缓解写压力。因为只有一个master,只有master才能进行写操作
(2)在Redis Sentinel模式中,每个节点需要保存全量数据,冗余比较多
所以,从3.0版本之后,官方推出了Redis Cluster,它的主要用途是实现数据分片(Data Sharding),不过同样可以实现HA,是官方当前推荐的方案。
- Redis-Cluster采用无中心结构
- 只有当集群中的大多数节点同时fail整个集群才fail。
- 整个集群有16384个slot,当需要在 Redis 集群中放置一个 key-value 时,根据 CRC16(key) mod 16384的值,决定将一个key放到哪个桶中。读取一个key时也是相同的算法。
- 当主节点fail时从节点会升级为主节点,fail的主节点online之后自动变成了从节点
当发生了故障之后,整个集群是怎么做的?(故障转移)
- Redis 集群中每个节点会与其他节点定期交换信息,这些信息会被用于判断某个节点的状态。
- 当一个主节点宕机时,其他节点会检测到它长时间未响应,并将其标记为主观下线(PFAIL,Partial Failure)。
- 如果多个主节点都认为该节点宕机,它们会相互验证,达到一致意见后,将该节点标记为客观下线(FAIL,Failure)。
- 这时,集群确认该节点已经失效,不再处理请求,接下来会启动故障转移流程。
- 故障的主节点拥有的分片数据会被自动转移到它的从节点中,以便继续提供服务。
- 集群中的健康主节点会发起从节点选举,选择一个从节点来接管原主节点的角色。
- 从节点中优先选择最新的数据副本接任主节点。如果多个从节点满足条件,会按优先级或ID来选择一个。
- 被选中的从节点将成为新的主节点,其他从节点会自动开始跟随新主节点。
- 集群中其他节点会被通知,更新其元数据以识别新主节点。此后,所有指向旧主节点的数据请求将被重定向到新主节点。
以上就是redis cluster中的故障转移整个流程
cluster的数据分片策略
Redis-cluster分片策略,是用来解决key存储位置的,这样就可以将key均衡的存储到不同的master中,共同对外提供服务
常见的数据分片的方式:顺序分片、哈希分片、节点取余哈希、一致性哈希..
那redis当中的cluster采用了什么分片策略呢?
Redis 集群没有使用一致性hash, 而是引入了 哈希槽的概念.
预设虚拟槽,每个槽就相当于一个数字,有一定范围(0到16383)
我们来看一下分配的流程步骤:
-
1.把16384槽按照节点数量进行平均分配,由节点进行管理
-
2.对每个key按照CRC16规则进行hash运算
-
3.把hash结果对16383进行取余
-
4.把余数发送给Redis节点
-
5.节点接收到数据,验证是否在自己管理的槽编号的范围
- 如果在自己管理的槽编号范围内,则把数据保存到数据槽中,然后返回执行结果
- 如果在自己管理的槽编号范围外,则会把数据发送给正确的节点,由正确的节点来把数据保存在对应的槽中
2、集群搭建
先来预览一下大致的步骤:
- 启动节点:将节点以集群方式启动,此时节点是独立的。
- 节点握手:将独立的节点连成网络。
- 槽指派:将16384个槽位分配给主节点,以达到分片保存数据库键值对的效果。
- 主从复制:为从节点指定主节点。
1)创建并启动集群的所有节点
新建目录,并拷贝出6个节点的配置文件
mkdir /usr/local/redis/redis-cluster
cd /usr/local/redis/redis-cluster
mkdir 900{1,2,3,4,5,6}
将redis.conf,依次拷贝到每个900X目录内,并修改每个900X目录下的redis.conf配置文件:
cd /usr/local/redis/redis-cluster/9001
cp /usr/local/redis/bin/redis.conf ./
vim redis.conf
9002、9003等等都是类似的步骤
以集群方式启动
# cluster-enabled yes 将前面的 # 去掉
启动这些服务
redis-server /usr/local/redis/redis-cluster/9001/redis.conf --port 9001
redis-server /usr/local/redis/redis-cluster/9002/redis.conf --port 9002
redis-server /usr/local/redis/redis-cluster/9003/redis.conf --port 9003
redis-server /usr/local/redis/redis-cluster/9004/redis.conf --port 9004
redis-server /usr/local/redis/redis-cluster/9005/redis.conf --port 9005
redis-server /usr/local/redis/redis-cluster/9006/redis.conf --port 9006
查看进程
2)将独立的节点连成网络
#replicas表示副本数,如果指定1则表示1个从库做备用
redis-cli --cluster create 127.0.0.1:9001 127.0.0.1:9002 127.0.0.1:9003 --cluster-replicas 1
参数解释:
- –cluster-replicas 1:表示希望为集群中的每个主节点创建一个从节点(一主一从)。
- –cluster-replicas 2:表示希望为集群中的每个主节点创建两个从节点(一主二从)。
中间的127.0.0.1:9001/127.0.0.1:9002/127.0.0.1:9003表示三个master节点
如果节点上有数据,可能会有错误提示:
[ERR] Node 127.0.0.1:8004 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.
解决办法:删除dump.rdb,nodes.conf,登录redis-cli,flushdb即可
如果没问题,将收到集群创建成功的消息:
3)集群验证
cluster命令验证
#使用redis-cli登录任意节点,使用cluster nodes可以查看集群信息
127.0.0.1:9001> cluster nodes
39c613372129fe80fe93b6fb3070f9562c315a59 127.0.0.1:9001@18082 master - 0 1615193645000 2 connected 5461-10922
725c09c568cb4010afe84d5cb4672fff5a248879 127.0.0.1:9002@18083 master - 0 1615193645976 3 connected 10923-16383
9fad54e90628814c1b2a5b57c2ad22b92f0f7b05 127.0.0.1:9003@18081 myself,master - 0 1615193644000 1 connected 0-5460
使用key值和数据验证
#注意,redis-cli参数:
# -c : 自动重定向到对应节点获取信息,如果不加,只会返回重定向信息,不会得到值#不加 -c
[root@ src]# redis-cli -p 9001
127.0.0.1:9001> set a a
(error) MOVED 15495 127.0.0.1:8083#加上 -c
[root@ src]# redis-cli -p 9001 -c
127.0.0.1:9001> set a a
-> Redirected to slot [15495] located at 127.0.0.1:9003 #自动跳到9003
OK
127.0.0.1:9003> get a #可以成功get到a的值
"a"
4)集群节点扩容
按上面方式,新起一个redis , 9004端口
#第一个参数是新节点的地址,第二个参数是任意一个已经存在的节点的IP和端口
redis-cli --cluster add-node 127.0.0.1:9004 127.0.0.1:9001
使用redis-cli登录任意节点,使用cluster nodes查看新集群信息
127.0.0.1:9001> cluster nodes
#注意!新加进来的这个8084是空的,没有分配片段
eb49056da71858d58801f0f28b3d4a7b354956bc 127.0.0.1:9004@18084 master - 0 1602665893207 0 connected
16a3f8a4be9863e8c57d1bf5b3906444c1fe2578 127.0.0.1:9003@18082 master - 0 1602665891204 2 connected 5461-10922
214e4ca7ece0ceb08ad2566d84ff655fb4447e19 127.0.0.1:9002@18083 master - 0 1602665892000 3 connected 10923-16383
864c3f763ab7264ef0db8765997be0acf428cd60 127.0.0.1:9001@18081 myself,master - 0 1602665890000 1 connected 0-5460
重新分片
redis-cli --cluster reshard 127.0.0.1:9001redis-cli --cluster reshard 127.0.0.1:9001 --cluster-from
10ac7df576168e7f6ec86b20b249e02b1fc13a25,43284b05c5a359b28507b49c29a49637f1f6312b,02a79c59682b7c05f13d41e46e814fc792fa2c50 --cluster-to 07e3416aba80cfb8a8ef81d27228559e5a9d6415 --cluster-slots 1024
#根据提示一步步进行,再次查看node分片,可以了!
127.0.0.1:8081> cluster nodes
eb49056da71858d58801f0f28b3d4a7b354956bc 127.0.0.1:9004@18084 master - 0 1602666306047 4 connected 0-332 5461-5794 10923-11255
16a3f8a4be9863e8c57d1bf5b3906444c1fe2578 127.0.0.1:9003@18082 master - 0 1602666305045 2 connected 5795-10922
214e4ca7ece0ceb08ad2566d84ff655fb4447e19 127.0.0.1:9002@18083 master - 0 1602666305000 3 connected 11256-16383
864c3f763ab7264ef0db8765997be0acf428cd60 127.0.0.1:9001@18081 myself,master - 0 1602666303000 1 connected 333-5460
平衡哈希槽:
这一步,是为了保证redis哈希槽的在每一个节点的均衡,需要对哈希槽进行均衡
redis-cli --cluster rebalance 127.0.0.1:9001