Redis-主从、哨兵、集群

123 阅读11分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情

一、集群

1、必要性

1、单个redis存在不稳定性。当redis服务宕机了,就没有可用的服务了

2、单个redis的读写能力是有限的。

总结:redis集群是为了强化redis的读写能力。

2、说明

1、redis集群中,每一个redis称之为一个节点。

2、redis集群中,有两种类型的节点:主节点(master)、从节点(slave)。

3、redis集群,是基于redis主从复制实现。

3、主从复制

主从复制模型中,有多个redis节点。 其中,有且仅有一个为主节点Master。从节点Slave可以有多个。

只要网络连接正常,Master会一直将自己的数据更新同步给Slaves,保持主从同步。

1)、特点

1、主节点Master可读、可写.

2、从节点Slave只读。(read-only)

主从模型可以提高读的能力,在一定程度上缓解了写的能力。因为能写仍然只有Master节点一个,可以将读的操作全部移交到从节点上,变相提高了写能力。

2)、配置

主节点不需要修改, 从节点修改slaveof,后面改为主节点的ip和端口

3)、缺点

当主节点宕机了,整个集群就没有可写的节点了

4)、实现方式

1、slaveof命令,如:slaveof xxxx:6379,表示将xxxx:6379设置成当前实例的主节点

slaveof no one命令表示当前服务取消当从节点

不需要重启,但是不便于管理

2、配置

slaveof ip port
slave-read-only yes

统一配置,需要重启

查看偏移量:info replication命令

如果主节点master_repl_offset和从节点的offset相差太多,表示复制可以存在问题

5)、全量同步

image.png

  1. slave内部首先会发送一个psync的命令给master 这个命令第一个参数是runId,第二个参数是偏移量,而由于是第一次复制,slave不知道master的runId,也不知道自己偏移量,这时候会传一个问号和-1,告诉master节点是第一次同步。
  2. 当master接受到psync ? -1 时,就知道slave是要全量复制,就会将自己的runID和offset告知slave
  3. slave会将master信息保存
  4. master这时会做一个RDB的生成(bgsave)
  5. 将RDB发送给slave
  6. 将复制缓冲区记录的操作也发送给slave
  7. slave清空自己的所有老数据
  8. slave这时就会加载RDB文件以及复制缓冲区数据,完成同步。

全量复制开销

1.bgsave的开销,每次bgsave需要fork子进程,对内存和CPU的开销很大

2.RDB文件网络传输的时间(网络带宽)

3.从节点清空数据的时间

4.从节点加载RDB的时间

5.可能的AOF重写时间(如果我们的从节点开启了AOF,则加载完RDB后会对AOF进行一个重写,保证AOF是最新的)

6)、部分复制

image.png

部分复制是 Redis 2.8 以后出现的,之所以要加入部分复制,是因为全量复制会产生很多问题,比如像上面的时间开销大、无法隔离等问题, Redis 希望能够在 master 出现抖动(相当于断开连接)的时候,可以有一些机制将复制的损失降低到最低

1、如果网络抖动(连接断开 connection lost) 2、主机master 还是会写 replbackbuffer(复制缓冲区) 3、从机slave 会继续尝试连接主机 4、从机slave 会把自己当前 runid 和偏移量传输给主机 master,并且执行 pysnc 命令同步 5、如果 master 发现你的偏移量是在缓冲区的范围内,就会返回 continue 命令 同步了 offset 的部分数据,所以部分复制的基础就是偏移量 offset。

注意: 正常情况下redis是如何决定是全量复制还是部分复制? 从节点将offset发送给主节点后,主节点根据offset和缓冲区大小决定能否执行部分复制: 1.如果offset偏移量之后的数据,仍然都在复制积压缓冲区里,则执行部分复制; 2.如果offset偏移量之后的数据已不在复制积压缓冲区中(数据已被挤出),则执行全量复制。

7)、主从复制常见问题

1、读写分离:读流量分摊到从节点

可能遇到的问题:复制数据延迟、读到过期数据、从节点故障

2、主从配置不一致

如maxmemory不一致:丢失数据

如数据结构优化参数(hash-max-ziplist-entries):内存不一致

3、规避全量复制

第一次全量复制不可避免;小主节点;低峰如:夜间访问量低时

节点运行ID不匹配:如一主一从配置,主节点重启(运行id变化);故障转移如:哨兵和集群

复制积压缓冲区不足,网络中断,部分复制无法满足;解决:增大复制缓冲区配置rel_backlog_size,网络增强

4、规避复制风暴

单主节点复制风暴:主节点重启,多从节点复制;解决:更换复制拓扑

单机器复制风暴:机器宕机重启,多主节点造成大量全量复制;解决:主节点分散多机器

4、Sentine哨兵模式

在主节点宕机的情况下,能够将从节点变成一个主节点

Redis 的 Sentinel 系统用于管理多个 Redis 服务器(instance), 该系统执行以下三个任务:

监控(Monitoring) : Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。

提醒(Notification) : 当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知

自动故障迁移(Automatic failover) : 当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作, 它会进行选举,将其中一个从服务器升级为新的主服务器, 并让失效主服务器的其他从服务器改为复制新的主服务器; 当客户端试图连接失效的主服务器时, 集群也会向客户端返回新主服务器的地址, 使得集群可以使用新主服务器代替失效服务器。

1)、监控

Sentinel可以监控任意多个Master和该Master下的Slaves。(即多个主从模式)

同一个哨兵下的、不同主从模型,彼此之间相互独立。

Sentinel会不断检查Master和Slaves是否正常。

2)、自动故障切换(Automatic failover)

监控同一个Master的Sentinel会自动连接,组成一个分布式的Sentinel网络,互相通信并交换彼此关于被监视服务器的信息

疑问:为什么要使用sentinel网络呢?

答:当只有一个sentinel的时候,如果这个sentinel挂掉了,那么就无法实现自动故障切换了。

故障切换的过程

1、投票 (半数原则) :当任何一个Sentinel发现被监控的Master下线时,会通知其它的Sentinel开会,投票确定该Master是否下线(半数以上,所以sentinel通常配奇数个)。

2、选举 :当Sentinel确定Master下线后,会在所有的Slaves中,选举一个新的节点,升级成Master节点。其它Slaves节点,转为该节点的从节点。

3、原Master重新上线 :当原Master节点重新上线后,自动转为当前Master节点的从节点

3)、部署

前提:已经存在一个正在运行的主从模式。

另外,配置三个Sentinel实例,监控同一个Master节点

没搭建过。。。。跳过

5、Cluster模式

官方提供的分布式解决方案

是sentinel和主从模式的结合体,通过cluster可以实现主从和master重选功能

Redis的数据是根据一定规则分配到cluster的不同机器,当数据量过大时,可以新增机器进行扩容。

每个集群中至少需要三个主数据库才能正常运行,所以redis集群至少需要一个备份节点,才能更好的保证集群的高可用

1)、分区和槽slot

redis cluster中有一个16384(2^4 * 2^10)长度的槽的概念。通过哈希算法再加上取模运算可以将一个值固定地映射到某个区间,区间由连续的slot组成。

redis cluster采用虚拟槽分区,所有的键根据哈希函数(CRC16[key]&16383)映射到0-16383槽内,共16384个槽位,每个节点维护部分槽及槽所映射的键值数据

哈希函数: Hash()=CRC16[key]&16383 按位与

redis用虚拟槽分区原因:解耦数据与节点关系,节点自身维护槽映射关系,分布式存储

2)、特点

多个redis节点网络互联,数据共享

所有的节点都是一主一从(也可以是一主多从),其中从不提供服务,仅作为备用

不支持同时处理多个key(如MSET/MGET),因为redis需要把key均匀分布在各个节点上, 并发量很高的情况下同时创建key-value会降低性能并导致不可预测的行为

支持在线增加、删除节点

客户端可以连接任何一个主节点进行读写

二、搭建redis集群Cluster(window)

1、解压安装包并赋值6份

2、修改各个redis的配置文件redis.windows.conf

bind 10.9.14.82 //服务器ip地址
port 6381 //端口6381--6386
cluster-enabled yes //打开集群
cluster-config-file nodes-6381.conf //nodes-6381.conf---condes-6386.conf
cluster-node-timeout 15000 //请求超时

3、安装Ruby运行环境

下载dl.bintray.com/oneclick/ru… (rubyinstaller-2.3.3-x64.exe)

运行安装三个选择框都打勾

注意:系统变量里面 path 需要配置 ruby的安装目录bin

PATHEXT 需要配置 .RB;.RBW

4、安装Redis的Ruby驱动redis-xxxx.gem

下载rubygems.org/pages/downl… (rubygems-update-3.1.4.gem)

切换到安装目录执行命令:gem install redis

5、安装集群脚本redis-trib (redis-trib.rb)

下载连接不可用,网上找资源

保存到某个redis目录下

6、创建集群

注意:

1、创建集群前删除dump.rdb和nodes-xxx.conf文件

2、每个redis节点都不能有数据

3、密码和集群密码都不能设置,创建集群后可以改配置文件设置密码和集群密码

4、flushall清除数据库数据

// 创建命令
ruby redis-trib.rb create --replicas 1 127.0.0.1:9000 127.0.0.1:9001 127.0.0.1:9002 127.0.0.1:9003 127.0.0.1:9004 127.0.0.1:9005
--replicas 1 表示每个主数据库拥有从数据库个数为1。master节点不能少于3个,所以我们用了6个redis

三、搭建redis集群Cluster(Linux)

1、安装redis

先编译安装一个redis,然后复制bin文件夹和配置文件

// 创建集群文件夹
mkdir /usr/local/redis-cluster
// 复制
cd /usr/local/redis
cp -r /usr/local/redis/bin /usr/local/redis-cluster/redis80
cp -r /usr/local/redis/bin /usr/local/redis-cluster/redis81
cp -r /usr/local/redis/bin /usr/local/redis-cluster/redis82
cp -r /usr/local/redis/bin /usr/local/redis-cluster/redis83
cp -r /usr/local/redis/bin /usr/local/redis-cluster/redis84
cp -r /usr/local/redis/bin /usr/local/redis-cluster/redis85

修改所有节点的配置文件

cd /usr/local/redis-cluster/redis80
vi redis.conf
​
#bind 127.0.0.1 远程访问注释掉 如果跨服务器则不能注释,填服务器ip
设置protected-mode 为 no
设置daemonize 为yes // 后台运行
#requirepass xxx 密码先注释掉,集群搭建成功再设置
#masterauth xxx  集群密码先注释掉,集群搭建成功再设置
设置cluster-enabled 为yes
cluster-config-file 放开注释

2、设置一键启动所有节点

cd /usr/local/redis-cluster
// 创建脚本文件
vi start-all.sh
​
cd redis80
./bin/redis-server redis.conf
cd ..
cd redis81
./bin/redis-server redis.conf
cd ..
cd redis82
./bin/redis-server redis.conf
cd ..
cd redis83
./bin/redis-server redis.conf
cd ..
cd redis84
./bin/redis-server redis.conf
cd ..
cd redis85
./bin/redis-server redis.conf
cd ..
    
// 修改脚本文件权限
chmod +x start-all.sh
​
// 一键启动
cd /usr/local/redis-cluster
./start-all.sh

3、安装ruby

注意:不要在线安装,在线安装的版本太低,推荐离线安装,去官网下载安装包

// 上传安装包ruby-2.3.8.tar.gz解压
cd /usr/local/redis-cluster/ruby-2.3.8
// 编译安装-prefix是将ruby安装到指定目录,也可以自定义 (过程几分钟)
./configure –-prefix=/usr/local/redis-cluster/ruby
make && make install 
​
// 验证是否安装成功
./ruby -v
​
// 设置环境变量
vi /etc/profile
export PATH=/usr/local/redis-cluster/ruby/bin:$PATH
​
// 保存退出执行
source /etc/profile

4、安装ruby驱动

cd /usr/local/redis-cluster
// 上传文件rubygems-update-3.1.4.gem
​
// 运行 
gem install rubygems-update-3.1.4.gem

5、创建集群

在redis的安装文件src里的redis-cli文件复制到集群目录

cd /redis-5.0.4/src
cp redis-cli /usr/local/redis-cluster
​
cd /usr/local/redis-cluster
./redis-cli --cluster create --cluster-replicas 1 127.0.0.1:9000 127.0.0.1:9001 127.0.0.1:9002 127.0.0.1:9003 127.0.0.1:9004 127.0.0.1:9005
    
// 连接某个节点
./redis-cli -p 9000 -c
// 查看集群信息
cluster info
// 查看集群连接信息
cluster nodes
​
// 修改密码,所有节点都修改
cd /usr/local/redis-cluster/redisxx
vi redis.conf
​
requirepass xxx
masterauth xxx
​
// 全部修改完,关闭当前集群所有节点
pa aux | grep redis
kill -9 进程号
​
// 一键启动所有节点
cd /usr/local/redis-cluster/
./start-all.sh