目录
一、单机redis的风险与问题
二、多台redis服务器连接方案
三、主从复制介绍
3.1、建立连接阶段工作流程
3.2、数据同步阶段
3.2.1、同步时注意点
3.3、命令传播阶段的部分复制
3.3.1、命令传播阶段出现的断网现象
3.3.2、部分复制的三个核心要素
3.4、数据同步+命令传播阶段工作流程
3.5、心跳机制
3.6、主从复制常见问题
3.6.1、频繁的全量复制
3.6.2、频繁网络中断(1)
3.6.3、频繁网络中断(2)
3.6.4、数据不一致问题
四、搭建
4.1、主机配置
4.2、从机配置文件内容
4.3、验证
一、单机redis的风险与问题
- 问题1. 机器故障
现象:硬盘故障、系统崩溃
本质:数据丢失,很可能对业务造成灾难性问题。
结论:基本上会泛起使用redis.
- 问题2. 容量瓶颈
现象:内存不足,从16G升级到最大内存。
本质:穷,硬件条件跟不上。
结论:放弃使用redis
- 结论:
为了避免单点Redis服务器故障,准备多台服务器,互相连通。将数据复制多个副本保存在不同的服务器上,链接在一起,并保证数据是同步的。即使其中一台服务器宕机,其他服务器依然可以继续提供服务,实现Redis的高可用,同时实现数据冗余备份。
二、多台redis服务器连接方案
- 提供数据方:master——主服务器,主节点,主库;主客户端
- 接收数据方:slave——从服务器,从节点,从库;从客户端
- 需要解决的问题: 数据同步
- 核心工作: master的数据复制到slave中。
三、主从复制介绍
概念:主从复制即将master中的数据即时、有效的复制到slave中。
特征:一个master可以拥有多个slave, 一个slave只对应一个master。
职责:
- master:
- 写数据
- 执行写操作时,将出现变化的数据自动同步到slave
- 读数据(禁止,从节点读数据)
- slave:
- 读数据
- 写数据(禁止,主节点写数据)
作用:
- 读写分离:master写、slave读,提供高服务器的读写负载能力
- 负载均衡:基于主从接口,配合读写分离,由slave分担master负载,并根据需求的变化,改变slave的数量,通过多个从节点分担数据读取负载,大大提高Redis服务器并发量和数据吞度量。
- 故障恢复:当master出现问题时,由slave提供服务,实现快速的故障恢复。
- 高可用基石:基于主从复制,构建哨兵模式与集群,实现Redis的高可用方案。
工作流程:分为三个阶段
- 建立链接阶段
- 数据同步阶段
- 命令传播阶段
3.1、建立连接阶段工作流程
描述:
步骤1:设置master的地址和端口,保存master信息。
步骤2:建立socket连接
步骤3:发送ping命令(定时器任务)
步骤4:身份验证
步骤5:发送slave端口信息
最后: 主从连接成功。
连接后的状态:
slave: 保存master的地址与端口。
master:保存slave的端口。
3.2、数据同步阶段
描述:
步骤1:请求同步数据
步骤2:创建RDB同步数据
步骤3:恢复RDB同步数据
步骤4:请求部分同步数据
步骤5:恢复部分同步数据
步骤6:数据同步工作完成。
最后: 主从同步成功并恢复正常连接。
最后的状态:
slave: 具有master端全部数据,包含RDB过程接收的数据。
master: 保存slave当前数据同步的位置。
注意重点:同步RDB文件时的过程叫“全量复制”,而同步复制缓冲区数据时的过程叫“部分复制”或“增量复制”。
3.2.1、同步时注意点
数据同步阶段master注意点:
1. 如果master数据量巨大,数据同步阶段应避开流量高峰期,避免造成master阻塞,影响业务正常执行。
2. 复制缓存区带下设定不合理,会导致数据溢出。如进行全量复制周期太长,进行部分复制时发现数据已经存在丢失的情况,必须进行第二次全量复制,致使slave陷入死循环状态。配置文件中,默认复制缓存区大小是1Mb(一般我们不改动它:过大会占用内存,恢复时间比较慢,过小会丢失很多数据)。
repl-backlog-size 1mb
3. master单机内存占用主机内存的不应过大,建议使用50%~70%内存,留下30%~50%的内存用于执行bgsave命令和创建复制缓冲区。
数据同步阶段slave注意点:
1. 为避免slave进行全量复制、部分复制时服务器响应阻塞或数据不同步,建议关闭此期间的对外服务。
slave-serve-stale-data yes|no
2. 数据同步阶段,master发送给slave信息可以理解成master是slave的一个客户端,主动向slave发送命令。
3. 多个slave同时对master请求数据同步,master发送的RDB文件争夺,会对带宽造成巨大冲击,如果master宽带不足,因此数据同步需要根据业务需求,适量错开高峰期。
4. slave过多时,建议调整拓扑结构,由一 主多从结构变为树状结构中间的节点即是master,也是slave。注意使用树状结构时,由于层级深度,导致深度越高的slave与最顶层master间数据同步延迟较大,数据一致性变差,应谨慎选择。
3.3、命令传播阶段的部分复制
3.3.1、命令传播阶段出现的断网现象
1.1、网络闪断闪现——忽略
1.2、短时间网络中断——部分复制
1.3、长时间网络中断——全量复制
3.3.2、部分复制的三个核心要素
3.3.2.1、服务器运行ID(runid)
概念: 服务器运行ID是每一台服务器每次运行的身份识别码,一台服务器多次运行可以生成多个运行id。
组成:运行id由40位字符组成,是一个随机的十六进制字符,例如:ff637f23132eb6e26729320ddaead5b0be30e284。
作用:运行id被用于服务间进行传输,识别身份如果想两次操作均对同一台服务器进行,必须每次操作携带对应的运行id,用于识别对方。
实现方式:运行id在每台服务器时自动生成,master在首次链接slave时,会将自己的运行ID发给slave, slave保存此ID(在客户端,通过info命令,可以查看节点的runId)。
3.3.2.2、复制积压缓冲区
概念:复制缓冲区,又名复制积压缓冲区,是一个先进先出(FIFO)的队列,用户缓存服务执行过的命令,每次传播命令,master都会将传播的命令记录下来,并存储在复制缓冲区。复制缓冲区默认数据存储空间大小是1M,由于存储空间大小是固定的,当入队元素的数量大于队列长度时,最先入队的元素会被弹出,而新元素会被放入队列。
由来:每台服务器启动时,如果开启右AOF或被连接成为master节点,即创建复制缓冲区。
作用:用户保存master收到的所有指令(仅影响数据变更的指令,例如set、select)。
数据来源:当master接收到主客户端的指令时,除了将指令执行,会将该指令存储到缓冲区中。
3.3.2.3主从服务器复制偏移量(offset)
概念:一个数字,描述复制缓冲区中的指令字节位置。
分类:
master复制偏移量:记录发送非所有slave的指令自己对应的位置(多个)
slave复制偏移量:记录slave接收master发送过来的指令字节对应的位置(一个)。
数据来源:
master端:发送一次记录一次。
slave端:接收一次记录一次。
作用:同步信息,比对master与slave的同步数据的差异,当slave断线后,恢复数据使用到。
复制缓冲区内部工作原理如下图:
描述:保存的数据格式如AOF文件内容,队列里保存字节值和偏移量。master记录已发送的信息对应的offset, slave也同事记录已接收的信息对应offset,防止master与slave的offset对不上。
3.4、数据同步+命令传播阶段工作流程
3.5、心跳机制
概念:进入命令传播阶段之后,master与slave需要进行信息交换,使用心跳机制进行维护,实现双方链接保持在线。
master心跳:
指令:PING
周期:由repl-ping-slave-period决定,默认10秒
作用:判断slave是否在线
查询:INFO replication——获取slave最后一次连接时间间隔,lag项维持在0或1的值时视为正常。
slave心跳任务:
指令:REPLCONF ACK {offset}
周期:1秒
作用1:汇报slave自己的复制偏移量,获取最新的数据变更指令
作用2:判断master是否在在线。
3.6、主从复制常见问题
3.6.1、频繁的全量复制
伴随着系统的运行,master的数据量会越来越大,一旦master重启,runid将发生变化,会导致全部slave的全量复制。
redis内部优化调整方案:
1).master内部创建master_replid变量,使用runid相同的策略生成,长度41位,并发给所有slave.
2).在master关闭时执行命令shutdown save, 进行RDB持久化,将runid与offset保存到RDB文件中。
repl-id repl-offset
通过redis-check-rdb命令可以查看该信息,如:
3).master重启后加载RDB文件,恢复数据
重启后,将RDB文件中保存的repl-id与repl-offset加载到内存中
master_repl_id=repl master_repl_offset = repl-offset
通过info命令可以查看该信息,如:
作用:本机保存上次runid,重启后恢复该值,使所有slave认为还是之前的master。
3.6.2、频繁网络中断(1)
3.6.2.1、问题现象——slave与master链接断开。
3.6.2.2、问题原因:
1)master发送ping指令频率较低。
2)master设定超时时间较短。
3)ping指令在网络中存在丢包。
3.6.2.3、解决方案——提高ping指令发送的频率。
repl-ping-slave-period
超时时间repl-time的时间至少是ping指令频率的5~10倍,否则slave很容易判断超时。
3.6.2.4、解决方案——通过设置合理的超时时间,确认是否释放slave.
3.6.3、频繁网络中断(2)
3.6.3.1、问题现象——master的CPU占用过高 或 slave平凡断开链接。
3.6.3.2、问题原因:
1)slave每1秒发送REPLCONF ACK命令道master。
2)当slave接到了慢查询时(keys *, hgetall等),会大量占用CPU性能。
3)master每1秒调用复制定时函数replicationCorn(), 比对slave发现长时间没有进行响应。
3.6.3.3、最终结果——master各种资源(输出缓冲区、宽带、连接等)被严重占用。
3.6.3.4、解决方案——通过设置合理的超时时间,确认是否释放slave.
repl-timeout
该参数定义了超时时间的阈值(默认60秒),超过该值,释放slave。
3.6.4、数据不一致问题
3.6.4.1、问题现象——多个slave获取相同数据不同步。
3.6.4.2、问题原因——网络信息不同步,数据发送有延迟。
3.6.4.3、解决方案
1)、优化主从间的网络环境,通常放置在同一机房部署,如果使用阿里云服务器时要注意此现象。
2)、监控主从节点延迟(通过offset)判断,如果slave延迟过大,暂时屏蔽程序对该slave的数据访问。
slave-serve-stale-data yes|no
开启后仅响应info、slaveof等少数命令(慎用,除非对数据一致性要求很高)。
四、搭建
打开Redis官网下载稳定版本(我这里是4.0.9)下载安装(window版本的redis下载路径:Tags · microsoftarchive/redis · GitHub)。
在opt目录下载, 命令“tar -zxvf redis-4.0.9.tar.gz”解压。
查看MakeIile文件内容,改文件是指定安装的目录。
命令:cat Makefile
执行安装命令: make install
注意:如果安装时出现"gcc: Command not found",如下:
则表示你的linux版本有可能是简单版本,需要执行安装gcc插件命令:
安装gcc插件:yum -y install gcc automake autoconf libtool make
扩展:gcc是什么?请点击linux中的gcc是什么-linux运维-PHP中文网
安装完gcc插件后,需要执行命令“make distclean”,否则会报“jemalloc/jemalloc.h: No such file or directory 错误”,这是因为前一次没有安装gcc插件导致安装失败产生的问题,所以需要清除目录再安装,命令如下:
make distclean && make install
安装完之后,src目录下就有我们需要的各种启动文件了:
4.1、主机配置
回到redis-4.0.9目录,复制redis.conf为另外一个要部署的文件,并对其进行修改(一般原始文件配置内容不动,如果部署的配置文件被该乱,可以快速从原始文件复制)。
命令:cp redis.conf redis-6379.conf
过滤掉注释和空白行显示redis.conf内容。
过滤注释: cat 文件名 | grep -v "#"
过滤空白行: cat 文件名| grep -v '^$'
cat redis.conf | grep -v '#' |grep -v '^$' > redis-6379.conf
现在编辑redis-6379.conf内容,其中内容很多,我们留几个核心配置(其中dir指定的目录是data,需要在redis-4.0.9创建data目录),内容如下:
protected-ddmode yes port 6379 daemonize yes logfile "6379.log" dir ./data
配置注释如下:
在redis-4.0.9目录指定配置文件执行启动redis命令,并通过查询进程判断是否启动成功。
[root@localhost redis-4.0.9]# redis-server redis-6379.conf
然后记得防火墙开启端口号:
命令:firewall-cmd --zone=public --add-port=6379/tcp --permanent //放开端口号
命令:firewall-cmd --reload //重新加载配置
查看防火墙状态
firewall-cmd --state
停止firewall
systemctl stop firewalld.service
4.2、从机配置文件内容
注意:新增slaveof后面链接的是主节点的ip和端口号。
port 6380 daemonize yes logfile "6380.log" dir ./data slaveof 192.168.187.132 6379
启动:
从redis日志文件同步主redis的关键日志:
8385:S 06 Oct 19:45:57.631 * Before turning into a slave, using my master parameters to synthesize a cached master: I may be able to synchronize with the new master with just a partial transfer.
8385:S 06 Oct 19:45:57.631 * Ready to accept connections
8385:S 06 Oct 19:45:57.634 * Connecting to MASTER 192.168.187.132:6379
8385:S 06 Oct 19:45:57.635 * MASTER <-> SLAVE sync started
8385:S 06 Oct 19:45:57.636 * Non blocking connect for SYNC fired the event.
8385:S 06 Oct 19:45:57.639 * Master replied to PING, replication can continue...
8385:S 06 Oct 19:45:57.641 * Trying a partial resynchronization (request b01c59b6577fe197ca3e3a6e1ca10bebaa6ec6ca:1).
8385:S 06 Oct 19:45:57.642 * Successful partial resynchronization with master.
8385:S 06 Oct 19:45:57.643 * MASTER <-> SLAVE sync: Master accepted a Partial Resynchronization.
主redis接收到从redis命令的关键日志:
6188:M 06 Oct 19:18:35.939 * Slave 192.168.187.138:6380 asks for synchronization
6188:M 06 Oct 19:18:35.940 * Full resync requested by slave 192.168.187.138:6380
4.3、验证
master客户端存入一个key为name,value为zhangshan的值。
注意:这里主机默认开启的6379端口号,所以使用客户端命令"redis-cli"链接时可以不写端口号。
slave客户端获取key为name元素:
注意:这里从机启动的端口号是6380,所以使用客户端命令"redis-cli"链接时需要指定端口号。
参考资料:
- redis 安装fatal error: jemalloc/jemalloc.h: No such file or directory 错误_baidu_38558076的博客-CSDN博客
- 黑马程序员Redis入门到精通,Java企业级解决方案必看_哔哩哔哩_bilibili



